I am working on a program that needs to have each exe signed before being packaged in the MSI deployment project. I've tried using VS2010's Signing tools ("Sign the Assembly"), but the key file doesn't seem to like VS2010. VS doesn't ask for a password or any of that and doesn't sign the exe's. So, I've been running the sign tool via post-build command line.
Before we get too involved, we should take a look at the current structure of the application (I don't have control over this. I'm just making the updater and trying to test packaging):
parent folder
Main EXE Project Folder
Updater EXE Project Folder
Service Project Folder
Installer Settings (uninstall processes, etc) Project Folder
Deployment Project Folder
Signing Files Folder
I read somewhere that the deployment project generates the exe in a different folder (obj/x86/Release/app.exe instead of bin/Release).
My current method of ensuring I sign the file is by hardcoding paths like this:
"..\..\..\..\SigningFolder\signtool" sign /f "..\..\..\..\SigningFolder\myKeyFile.p12" /p mypassword /t http://somecertsite.com "..\..\..\..\Updater\Updater\obj\x86\Release\Updater.exe"
"..\..\..\..\SigningFolder\signtool" sign /f "..\..\..\..\SigningFolder\myKeyFile.p12" /p mypassword /t http://somecertsite.com "..\..\..\..\Updater\Updater\bin\Release\Updater.exe"
This makes my eyes bleed. (This happens for each EXE and after the MSI is built, I sign the MSI as well.
So, my question:
Is there a way to target the absolute output of the path? If I use $(OutDir), it points to bin\Release when compiling via the deployment project. (Or generally... Is there a better way to do this?)
My method is to add the following line in my deployment project PostBuildEvent property (assuming I need to use a certificate stored on a smart card (/a option) and that the signtool path can't be determined via environment variables):
call "C:\Program Files (x86)\Windows Kits\8.0\bin\x86\signtool.exe" sign /a /d "$(SolutionName)" /q "$(BuiltOuputPath)"
This will sign the generated MSI, but not the enclosed EXE files.
For this, I also add the following lines in the Post-build event of my C# projects (Project > Properties > Build Events):
call "C:\Program Files (x86)\Windows Kits\8.0\bin\x86\signtool.exe" sign /a /d "$(SolutionName)" /q "$(TargetDir)$(TargetFileName)" "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"
Doing so will sign after a successfull build:
The EXE file builded from my C# project (under bin directory)
The EXE file used by my deployment project as "Primary output" (under obj directory)
And finally the MSI package
Then, at the end, I don't have any executable file unsigned which is what I was looking for :)
Related
I am using the following line in my Post-build event command line in VS2017:
xcopy /d /y "$(ProjectDir)dll\*.dll" "$(OutDir)"
to move dlls to the \bin\Debug folder when building. However the dlls in the dll directory end up in the folder \bin\Debug\bin\Debug. $(OutDir) is set to \bin\Debug. I have not touched or changed that from the default project generated. What reason would cause the path to be duplicated like that?
For this dll, I am unable to add it as a reference because it VS does not seem to support it (gives an unsupported/invalid error when I browse and add it). The dll does interface well in C# despite that.
I have a C# Visual Studio solution with about 15 projects. When I build the solution I want all DLL and EXE files for each project to go to a common folder (called Deploy).
The way I was thinking about doing it was, for each project's Post-build Event Command Line section put the following commands:
IF NOT EXIST $(SolutionDir)Deploy (
'If directory does not exist, create it
MKDIR $(SolutionDir)Deploy
) ELSE (
'Delete directory to make sure it's "clean"
RMDIR /F /S /Q $(SolutionDir)Deploy
MKDIR $(SolutionDir)Deploy
)
'Copy executable and required DLLs to Deploy directory
COPY /Y $(TargetPath) $(SolutionDir)Deploy
COPY /Y $(TargetDir)*.dll $(SolutionDir)Deploy
The problem with doing it this way, however, is I have 15 projects and would have put this in each individual project's post build event section and also, every time I add a new project, I would have to remember to do the same for it.
I checked the solution file properties and did not see a way to set a solution-wide post build event to copy all the files so I did a few Google searches.
One page said to use a C++ Makefile project. I added this type of project to my solution and clicked on the project properties page and found that there is a section under Configuration Properties->NMake with the following:
Build Command Line
Rebuild All Command Line
Clean Command Line
Using the Makefile project's Command Line option poses a similar problem to above. Many different commands to copy each of my 15 project's output files such as:
COPY /Y $(SolutionDir)Project1\bin\$(ConfigurationName)\*.exe $(SolutionDir)Deploy
COPY /Y $(SolutionDir)Project2\bin\$(ConfigurationName)\*.exe $(SolutionDir)Deploy
...
COPY /Y $(SolutionDir)Project15\bin\$(ConfigurationName)\*.exe $(SolutionDir)Deploy
There is another apparent problem with doing it this way. As you can see I took advantage of the $(SolutionDir) and $(ConfigurationName) macros but I had to hard-code each project name.
I didn't see any macros like $(AllProjects), $(AllProjectDirs), etc.
Also, it appears that command line commands for Makefile projects are for building, not post-build events, so I gave up on this idea altogether.
I then tried using a Visual Studio Installer project. After adding the project to my solution I right-clicked the project and saw that there was an Add->Project Output... option. This brought up a dialog allowing me to add one of my other project's Primary Output. I repeated this for each of my other projects and rebuilt.
What resulted was an .MSI file in the output folder. I then opened installer project properties and changed the Package files option to As loose uncompressed files and rebuilt. The output folder now contained all my project's EXE and DLL files!
Most people would be satisfied at this point and move on but I am the kind of person who likes to find the best way to do things.
There was one thing I didn't like about using the installer project option, the fact that, besides copying the files from all my projects, it also created an MSI file (which I don't need) and I didn't see any option tell it not to create one.
Can anyone recommend a another/better way to accomplish my goal of copying all project output files to a single folder?
Thank you.
P.S. I was thinking I could just make a batch file to search and copy all the EXE and DLL files to the Deploy folder but I would have to run the batch file outside of the Visual Studio IDE and also hard-code the configuration folder (Debug or Deploy).
Can't you just change the Output Directory of the C++ projects? See How to: Change the Build Output Directory.
On the menu bar, choose Project, Properties.
Expand the Configuration Properties node, and choose General.
Change the Output Directory value to the new output directory.
If you want both options, you can also create multiple configurations for your VS projects and solutions, similar to the standard "Debug" and "Release" ones. Create a new configuration from one of the existing ones, then change the output directory and save. Now you can just switch the configuration at the solution level to build into another directory. See this link for detailed steps:
How to: Create and Edit Configurations
I have configured pre build events for a proj in visual studio.
All the files are copied in a particular folder as a part of this build command.
Recently i have added crx and xpi files in source folder.
These files alone are not getting copied to the destination folder.
Here is the build command:copy "$(SolutionDir)DLLRequired*.*" "$(TargetDir)"
here even though i have used "*.*", it skips the crx and xpi files.
Please help.
If these files are part of your project - you need to right click on them, select properties and in Copy to Output Directory select Copy always.
If these files are dynamic or are not part of your project - you should try doing this: XCOPY $(ProjectDir)\Libs\DLLRequired*.* $(TargetDir) /Y /R - this is using ProjectDir instead of SolutionDir and should always work.
Also if something does not work - check out Output windows for any error messages.
I am currently creating a console application which is reading from a folder which contains xml files, like so:
/Templates/Create.xml
/Template/Update.xml
But when I debug the application it is looking for the files in /bin/Debug/Templates because I use: System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
So it is doing exactly what i want it to ..but is there any way to get Visual Studio to copy the folder and files automatically to the Debug/Release folder?
At the moment I have to keep the two folders updated.
I have done this before in a Windows application, but I can't seem to figure it out in a console
SOLUTION:
I added the following code in Pre-build:
XCOPY "$(ProjectDir)Templates" "$(TargetDir)Templates" /R /Y /I /T
..and it works like a charm
In visual studio you can have post build actions. In this you can write command to copy the xml to the Debug/Release folder depending upon your BuildMode.
Update:
In Project Properties you can find this.
I have a few VS 2010 C# projects that are shared between several solutions. I would like these projects to build to the directory of the solutions they are open in. How do I do this?
I considered setting up different build configurations (Debug_Xsln, debug_Ysln, Release_Xsln...) but wasn't sure if there was a better way.
http://msdn.microsoft.com/en-us/library/42x5kfw4(v=VS.100).aspx
You can use a postbuild event with xcopy and the macro $(SolutionName) or $(SolutionDir) to copy the compiled files into the correct folder.
Go into properties for the project, build events tab, and in Post Build event command line enter something like this:
xcopy "$(ProjectDir)bin\$(ConfigurationName)\*.*" "$(SolutionDir)$(ProjectName)\bin\$(ConfigurationName)" /i /d /y
The benefit of this method is you can copy the build output of one project to multiple locations
OR
(as Ziplin discovered)
If you only have one location you want the build output to go, you can use the macros above to set the output path, like this:
$(SolutionDir)$(ProjectName)\bin\$(ConfigurationName)
just go to the project properties on the build tab and set your macroed location as the output path