Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stub Executables #868

Merged
merged 14 commits into from
Nov 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion Squirrel.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Squirrel", "src\Squirrel\Squirrel.csproj", "{1436E22A-FE3C-4D68-9A85-9E74DF2E6A92}"
EndProject
Expand Down Expand Up @@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WriteZipToSetup", "src\Writ
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update-Mono", "src\Update\Update-Mono.csproj", "{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubExecutable", "src\StubExecutable\StubExecutable.vcxproj", "{C028DB2A-E7C5-4232-8C22-D5FBA2176136}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CIBuild|Any CPU = CIBuild|Any CPU
Expand Down Expand Up @@ -384,6 +386,7 @@ Global
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|x86.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Mono Release|x86.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Any CPU.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Any CPU.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|Mixed Platforms.Build.0 = Release|Win32
{4D3C8B70-075D-48A5-9FF3-EDB87347B136}.Release|x64.ActiveCfg = Release|Win32
Expand Down Expand Up @@ -437,6 +440,54 @@ Global
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x64.Build.0 = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x86.ActiveCfg = Release|Any CPU
{5B4BC824-73FC-49D7-BD9D-CE53AA1AA86E}.Release|x86.Build.0 = Release|Any CPU
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.CIBuild|x86.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Coverage|x86.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Any CPU.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Any CPU.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x64.ActiveCfg = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x64.Build.0 = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x86.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Debug|x86.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|Mixed Platforms.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x64.ActiveCfg = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x64.Build.0 = Debug|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x86.ActiveCfg = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Debug|x86.Build.0 = Debug|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Any CPU.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Any CPU.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Mono Release|x86.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Any CPU.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Any CPU.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|Mixed Platforms.Build.0 = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x64.ActiveCfg = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x64.Build.0 = Release|x64
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x86.ActiveCfg = Release|Win32
{C028DB2A-E7C5-4232-8C22-D5FBA2176136}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
4 changes: 2 additions & 2 deletions src/Setup/Setup.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
Expand Down Expand Up @@ -178,4 +178,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
1 change: 1 addition & 0 deletions src/Squirrel.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<file src="Squirrel\bin\Release\ICSharpCode.*" target="lib\Net45" />
<file src="Setup\bin\Release\Setup.exe" target="tools" />
<file src="WriteZipToSetup\bin\Release\WriteZipToSetup.exe" target="tools" />
<file src="StubExecutable\bin\Release\StubExecutable" target="tools" />
<file src="Update\bin\Release\Update.exe" target="tools\Squirrel.exe" />
<file src="Update\bin\Release\Update-Mono.exe" target="tools\Squirrel-Mono.exe" />
<file src="Update\bin\Release\Update.com" target="tools\Squirrel.com" />
Expand Down
26 changes: 20 additions & 6 deletions src/Squirrel/ReleasePackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,16 @@ await Utility.ForEachAsync(entries, (zipEntry) => {
if (!re.Match(entryFileName).Success) return;

var fullZipToPath = Path.Combine(outFolder, re.Replace(entryFileName, "", 1));

var failureIsOkay = false;
if (fullZipToPath.Contains("_ExecutionStub.exe")) {
// NB: On upgrade, many of these stubs will be in-use, nbd tho.
failureIsOkay = true;
fullZipToPath = Path.Combine(
Directory.GetParent(Path.GetDirectoryName(fullZipToPath)).FullName,
Path.GetFileName(fullZipToPath).Replace("_ExecutionStub.exe", ".exe"));
}

var directoryName = Path.GetDirectoryName(fullZipToPath);

var buffer = new byte[64*1024];
Expand All @@ -211,12 +221,16 @@ await Utility.ForEachAsync(entries, (zipEntry) => {
Utility.Retry(() => Directory.CreateDirectory(directoryName), 2);
}

Utility.Retry(() => {
using (var zipStream = zf.GetInputStream(zipEntry))
using (FileStream streamWriter = File.Create(fullZipToPath)) {
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
}, 5);
try {
Utility.Retry(() => {
using (var zipStream = zf.GetInputStream(zipEntry))
using (FileStream streamWriter = File.Create(fullZipToPath)) {
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
}, 5);
} catch (Exception e) {
if (!failureIsOkay) throw e;
}
}, 4);
} finally {
zf.Close();
Expand Down
51 changes: 14 additions & 37 deletions src/Squirrel/UpdateManager.ApplyReleases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ public Dictionary<ShortcutLocation, ShellLink> GetShortcutsForExecutable(string

var releases = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
var thisRelease = Utility.FindCurrentVersion(releases);
var updateExe = Path.Combine(rootAppDirectory, "update.exe");

var zf = new ZipPackage(Path.Combine(
Utility.PackageDirectoryForAppDir(rootAppDirectory),
Expand All @@ -168,14 +167,13 @@ public Dictionary<ShortcutLocation, ShellLink> GetShortcutsForExecutable(string

this.Log().Info("Creating shortcut for {0} => {1}", exeName, file);

ShellLink sl;
sl = new ShellLink {
Target = updateExe,
IconPath = exePath,
var target = Path.Combine(rootAppDirectory, exeName);
var sl = new ShellLink {
Target = target,
IconPath = target,
IconIndex = 0,
WorkingDirectory = Path.GetDirectoryName(exePath),
Description = zf.Description,
Arguments = "--processStart \"" + exeName + "\"",
};

if (!String.IsNullOrWhiteSpace(programArguments)) {
Expand All @@ -195,7 +193,6 @@ public void CreateShortcutsForExecutable(string exeName, ShortcutLocation locati

var releases = Utility.LoadLocalReleases(Utility.LocalReleaseFileForAppDir(rootAppDirectory));
var thisRelease = Utility.FindCurrentVersion(releases);
var updateExe = Path.Combine(rootAppDirectory, "update.exe");

var zf = new ZipPackage(Path.Combine(
Utility.PackageDirectoryForAppDir(rootAppDirectory),
Expand Down Expand Up @@ -225,13 +222,13 @@ public void CreateShortcutsForExecutable(string exeName, ShortcutLocation locati
this.ErrorIfThrows(() => Utility.Retry(() => {
File.Delete(file);

var target = Path.Combine(rootAppDirectory, exeName);
sl = new ShellLink {
Target = updateExe,
IconPath = icon ?? exePath,
Target = target,
IconPath = icon ?? target,
IconIndex = 0,
WorkingDirectory = Path.GetDirectoryName(exePath),
Description = zf.Description,
Arguments = "--processStart \"" + exeName + "\"",
};

if (!String.IsNullOrWhiteSpace(programArguments)) {
Expand Down Expand Up @@ -468,41 +465,21 @@ void updateLink(ShellLink shortcut, string newAppPath)
var targetIsUpdateDotExe = target.EndsWith("update.exe", StringComparison.OrdinalIgnoreCase);

this.Log().Info("Old shortcut target: '{0}'", target);

if (!targetIsUpdateDotExe) {
target = Path.Combine(newAppPath, Path.GetFileName(shortcut.Target));
target = Path.Combine(rootAppDirectory, Path.GetFileName(shortcut.Target));
} else {
target = Path.Combine(rootAppDirectory, Path.GetFileName(shortcut.IconPath));
}

this.Log().Info("New shortcut target: '{0}'", target);

shortcut.WorkingDirectory = newAppPath;
shortcut.Target = target;

// NB: If the executable was in a previous version but not in this
// one, we should disappear this pin.
if (!File.Exists(target)) {
shortcut.Dispose();
this.ErrorIfThrows(() => Utility.DeleteFileHarder(target), "Failed to delete outdated pinned shortcut to: " + target);
return;
}

this.Log().Info("Old iconPath is: '{0}'", shortcut.IconPath);
if (!File.Exists(shortcut.IconPath) || shortcut.IconPath.IndexOf("app-", StringComparison.OrdinalIgnoreCase) > 1) {
var iconPath = Path.Combine(newAppPath, Path.GetFileName(shortcut.IconPath));

if (!File.Exists(iconPath) && targetIsUpdateDotExe) {
var executable = shortcut.Arguments.Replace("--processStart ", "");
iconPath = Path.Combine(newAppPath, executable);
}

this.Log().Info("Setting iconPath to: '{0}'", iconPath);
shortcut.IconPath = iconPath;

if (!File.Exists(iconPath)) {
this.Log().Warn("Tried to use {0} for icon path but didn't exist, falling back to EXE", iconPath);

shortcut.IconPath = target;
shortcut.IconIndex = 0;
}
}
shortcut.IconPath = target;
shortcut.IconIndex = 0;

this.ErrorIfThrows(() => Utility.Retry(() => shortcut.Save(), 2), "Couldn't write shortcut " + shortcut.ShortCutFile);
this.Log().Info("Finished shortcut successfully");
Expand Down
31 changes: 31 additions & 0 deletions src/Squirrel/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,37 @@ public static async Task DeleteDirectoryOrJustGiveUp(string dir)
}
}

// http://stackoverflow.com/questions/3111669/how-can-i-determine-the-subsystem-used-by-a-given-net-assembly
public static bool ExecutableUsesWin32Subsystem(string peImage)
{
using (var s = new FileStream(peImage, FileMode.Open, FileAccess.Read)) {
var rawPeSignatureOffset = new byte[4];
s.Seek(0x3c, SeekOrigin.Begin);
s.Read(rawPeSignatureOffset, 0, 4);

int peSignatureOffset = rawPeSignatureOffset[0];
peSignatureOffset |= rawPeSignatureOffset[1] << 8;
peSignatureOffset |= rawPeSignatureOffset[2] << 16;
peSignatureOffset |= rawPeSignatureOffset[3] << 24;

var coffHeader = new byte[24];
s.Seek(peSignatureOffset, SeekOrigin.Begin);
s.Read(coffHeader, 0, 24);

byte[] signature = { (byte)'P', (byte)'E', (byte)'\0', (byte)'\0' };
for (int index = 0; index < 4; index++) {
if (coffHeader[index] != signature[index]) throw new Exception("File is not a PE image");
}

var subsystemBytes = new byte[2];
s.Seek(68, SeekOrigin.Current);
s.Read(subsystemBytes, 0, 2);

int subSystem = subsystemBytes[0] | subsystemBytes[1] << 8;
return subSystem == 2; /*IMAGE_SUBSYSTEM_WINDOWS_GUI*/
}
}

public static void LogIfThrows(this IFullLogger This, LogLevel level, string message, Action block)
{
try {
Expand Down
23 changes: 23 additions & 0 deletions src/StubExecutable/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
This executable uses the semver library from https://github.com/zmarko/semver, under the following license:

The MIT License (MIT)

Copyright (c) 2015 Marko Živanovc

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
62 changes: 62 additions & 0 deletions src/StubExecutable/ReadMe.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
========================================================================
WIN32 APPLICATION : StubExecutable Project Overview
========================================================================

AppWizard has created this StubExecutable application for you.

This file contains a summary of what you will find in each of the files that
make up your StubExecutable application.


StubExecutable.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.

StubExecutable.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).

StubExecutable.cpp
This is the main application source file.

/////////////////////////////////////////////////////////////////////////////
AppWizard has created the following resources:

StubExecutable.rc
This is a listing of all of the Microsoft Windows resources that the
program uses. It includes the icons, bitmaps, and cursors that are stored
in the RES subdirectory. This file can be directly edited in Microsoft
Visual C++.

Resource.h
This is the standard header file, which defines new resource IDs.
Microsoft Visual C++ reads and updates this file.

StubExecutable.ico
This is an icon file, which is used as the application's icon (32x32).
This icon is included by the main resource file StubExecutable.rc.

small.ico
This is an icon file, which contains a smaller version (16x16)
of the application's icon. This icon is included by the main resource
file StubExecutable.rc.

/////////////////////////////////////////////////////////////////////////////
Other standard files:

StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named StubExecutable.pch and a precompiled types file named StdAfx.obj.

/////////////////////////////////////////////////////////////////////////////
Other notes:

AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.

/////////////////////////////////////////////////////////////////////////////
Loading