I have several deployment projects. In order to deploy an application, I need to do several tasks, one of them is to change each deployment project's product version and product code.
I can't find a way to programmatically change them.
Since it's a Deployment project (which finally produces an executable installer), I'm not able to work with MSBuild, instead I'm using the Devenv from the command prompt.
I was searching for the exact same thing today. I found this using google:
static void Main(string[] args)
{
string setupFileName = #"<Replace the path to vdproj file>";
StreamReader reader = File.OpenText(setupFileName);
string file = string.Empty;
try
{
Regex expression = new Regex(#"(?:\""ProductCode\"" =
\""8.){([\d\w-]+)}");
Regex expression1 = new Regex(#"(?:\""UpgradeCode\"" =
\""8.){([\d\w-]+)}");
file = reader.ReadToEnd();
file = expression.Replace(file, "\"ProductCode\" = \"8:{" +
Guid.NewGuid().ToString().ToUpper() + "}");
file = expression1.Replace(file, "\"UpgradeCode\" = \"8:{"
+ Guid.NewGuid().ToString().ToUpper() + "}");
}
finally
{
// Close the file otherwise the compile may not work
reader.Close();
}
TextWriter tw = new StreamWriter(setupFileName);
try
{
tw.Write(file);
}
finally
{
// close the stream
tw.Close();
}
}
I know that the original poster is looking for a .NET 2.0 solution to this problem. However, since this wasn't tagged as .NET, I'll offer up my C++ solution to the problem. This may be applicable in .NET land, but I'll leave that to others.
This not only updates the version information in the about box and log file for my application, but also all of the Windows version info that is seen in Windows Explorer.
UPDATE: Added some changes that I've made to the process since my original answer.
First off, I moved the entire version info block from my Project.rc file to my Project.rc2 file:
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION FILE_VER
PRODUCTVERSION PROD_VER
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "MyCompany"
VALUE "FileDescription", "Software Description"
VALUE "FileVersion", 1,0,0,1
VALUE "InternalName", "FileName.exe"
VALUE "LegalCopyright", "(c) 2008 My Company. All rights reserved."
VALUE "OriginalFilename", "FileName.exe"
VALUE "ProductName", "Product Name"
VALUE "ProductVersion", 1,0,0,1
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
This essentially transports all of the version info stuff that you would edit from the resource editor into a separate file. This makes it so that you don't get errors when editing the resource file from outside of the editor. The downside is that you can no longer edit the version info from the resource editor. But, since we want this stuff updated automatically, that isn't a big deal.
Next, I created a VersionInfo.h file and added it to my project:
#pragma once
//major release version of the program, increment only when major changes are made
#define VER_MAJOR 2
//minor release version of the program, increment if any new features are added
#define VER_MINOR 0
//any bugfix updates, no new features
#define VER_REV 0
//if this is some special release (e.g. Alpha 1) put the special release string here
#define STR_SPECIAL_REL "Alpha 1"
#define FILE_VER VER_MAJOR,VER_MINOR,VER_REV
#define PROD_VER FILE_VER
//these are special macros that convert numerical version tokens into string tokens
//we can't use actual int and string types because they won't work in the RC files
#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)
#define STR_FILE_VER STRINGIZE(VER_MAJOR) "." STRINGIZE(VER_MINOR) "." STRINGIZE(VER_REV)
#define STR_PROD_VER STR_FILE_VER " " STR_SPECIAL_REL
#define STR_COPYRIGHT_INFO "©" BuildYear " Your Company. All rights reserved."
I then included VersionInfo.h in the rc2 file and made the following changes:
#include "VersionInfo.h"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
<no changes>
VALUE "FileVersion", STR_FILE_VER
<no changes>
VALUE "LegalCopyright", STR_COPYRIGHT_INFO
<no changes>
VALUE "ProductVersion", STR_PROD_VER
<no changes>
With this setup, I could edit my build script (which uses Perl) to modify the version info in the VersionInfo.h file before rebuilding the entire project using the devenv command line.
One additional step that I added that may also be of interest (although it is not completely perfected yet, and may be a future question here) is to generate a unique build number every time the project is built. In the current incarnation, it always works for complete rebuilds, but only sporadically on incremental builds. What I did was create a file called build_number.incl that contains the following:
#define CurrentBuildNumber "20081020P1525"
Which is essentially the date and time that the build was started. I created a batch file that is run as a pre-build event to the project that generates this file. The script also defines BuildYear so that the copyright in the VersionInfo.h file always contains the year of the most recent build. The batch script is the following:
echo Generating Build Number
#For /F "tokens=2,3,4 delims=/ " %%A in ('Date /t') do #(
Set Month=%%A
Set Day=%%B
Set Year=%%C
)
#For /F "tokens=1,2,3 delims=/M: " %%A in ('Time /t') do #(
Set Hour=%%A
Set Minute=%%B
Set AmPm=%%C
)
#echo #define CurrentBuildNumber "%Year%%Month%%Day%%AmPm%%Hour%%Minute%" > "$(ProjectDir)\build_number.incl"
#echo #define BuildYear "%Year%" >> "$(ProjectDir)\build_number.incl"
echo ----------------------------------------------------------------------
This file is then included in any file in the project that needs to use the build number (i.e. the about box).
Some of this was gleaned from this CodeProject post.
Hopefully this info proves helpful.
I had the same problem, and I found out that modifying the .vdproj file in a prebuildevent does not exactly do what I like.
I used some other code to modify the msi file file after the the setup project has been build, so I use the postbuildevent.
See my blog-post here.
We use a program that updates each AssemblyInfo.cs or AssemblyInfo.vb based on a configuration file value. we run this executable before each build. That was the best we could do to automate this process. You can add a call to this batch process in your projects configuration as a pre build step.
You could use the msbuild task to update you product version. Check out this post from the MSBuild team on this subject.
Embedding SVN Revision number at compile time in a Windows app
In my answer to this question, I describe how I accomplish this task using SVN.
This may not be quite what you're after, but way back in the mists of time I wrote something called stampver, which can auto-increment a build number directly in the .exe file as a post-build step.
Resource Tuner Console
This console resource editor allows creating a reliable and repeatable
process for updating Product Version Information resources during the final
stage of the build process from the command prompt.
See specifically the batch manipulation of file version information page for greater details:
http://www.reseditor.com/rtc-solution-version-info.htm
I know this a very old thread, but here's a vbs solution to achieve the same end. Simply place this in your deployment folder next to the .vdproj file.
Function CreateGuid()
CreateGuid = Left(CreateObject("Scriptlet.TypeLib").Guid,38)
End Function
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set fso = CreateObject("Scripting.FileSystemObject")
Set RegEx = CreateObject("VBScript.RegExp")
For Each file in fso.GetFolder(".").Files
if (fso.GetExtensionName(file.Name) = "vdproj") then
WScript.Echo "Updating: " + file.Name
Set oFile = fso.OpenTextFile(file.Name, ForReading, True)
fileContents = oFile.ReadAll
oFile.Close
RegEx.Pattern = """ProductCode"" = ""8:{.*-.*-.*-.*-.*}"
fileContents=Regex.Replace(fileContents, """ProductCode"" = ""8:" & CreateGuid)
Set oFile = fso.OpenTextFile(file.Name, ForWriting, True)
oFile.Write fileContents
oFile.Close
end if
Next
Then in your real project, have a post build event similar to:
cd $(SolutionDir)\CustomWebSetup
cscript -nologo UpdateProductCode.vbs
This will update the vdproj with a new ProductCode in preparation for the next build. After the build is complete, VS will prompt for a reload of the deployment project.
Look into the use of RCS, CVS and/or subversion. I am only familiar with RCS; my understanding is that CVS is based on RCS but more comprehensive. I have read on various boards that subversion is the better, but I have never used it. RCS has been adequate for keeping track of changes and versions on all my documents and software projects.
RCS is here: http://www.cs.purdue.edu/homes/trinkle/RCS/
CVS is here: http://www.nongnu.org/cvs/
Subversion is here: http://subversion.tigris.org/
Related
Trying to automate some of our processes in a C++ Windows app build using Jenkins. What we would like to do is make the updating of the version information in the resource file (.rc) automatic. Currently there is a script that prompts user for which version that they want to release, and preps everything for automated building, i.e. creates branch etc.
We would like part of the process to update the .rc file. Are there tools to edit .rc files programatically that can be run from the command line?
First of all, you should put the code below in a .rc2 file that is neither interpreted nor modified by Visual Studio and include that file in your .rc file.
In order to yield the version strings, you need two helper functions that concatenate the stringified numbers into a string.
The variables F1 through F4 can be defined by including a header file. Ideally you would create a header from the user input that defines just those four variables. This keeps the whole rest of your code base unchanged. The method is identical for the product verion.
#define F1 1 // Defined by an included header
#define F2 2
#define F3 3
#define F4 4
// MyAppVersionInfo.rc2
#define STRTMP(V1, V2, V3, V4) #V1 "." #V2 "." #V3 "." #V4
#define STR(V1, V2, V3, V4) STRTMP(V1, V2, V3, V4)
#define FVC F1,F2,F3,F4
#define FVS STR(F1,F2,F3,F4)
VS_VERSION_INFO VERSIONINFO
FILEVERSION FVC
...
VALUE "FileVersion", FVS
Note that I chose very short identifiers in this example to keep stackoverflow.com happy.
On windows, MZ/PE executables often have an attibute called "Original File Name", used to describe the original file name assigned to an executable file when it was created.
It is readable to a Windows user from the "Details" tab of the file's "Properties" window (opened by rightclicking a file and selecting "Properties").
I found many other questions that discuss "original file name, so to make it clear, I'm talking about this field, for the mspaint.exe file:
I however, whould like to access/read this attribute (and potentially edit it) using batch files or the windows command line (not powershell, please!).
Thanks!
Windows does not have a built-in command line tool to read version information from PE files.
You can use a resource editor like Resource Hacker to export information but you still have to parse the exported file.
On WinVista+ (and WinXP with desktop search installed) you can read the information using the shell property system (the same API used by the file properties dialog).
A Microsoft developer has created a free tool called shellproperty.exe that you can use to read the System.OriginalFileName property.
With Windows Script Host it is also possible to access the property system if you use the ShellFolderItem.ExtendedProperty method.
And finally, a WSH script can be merged with a batch file to create a working polyglot with zero external dependencies:
#if (1 == 0) #end /*
#cscript.exe /E:jscript /nologo "%~f0" %*
#goto :eof
*/
var objShell = new ActiveXObject("shell.application");
var objFolder2, ssfSysDir = 0x25, propVal = "";
objFolder2 = objShell.NameSpace(ssfSysDir);
if (objFolder2 != null)
{
var objFolderItem;
objFolderItem = objFolder2.ParseName("mspaint.exe");
if (objFolderItem != null)
{
propVal = objFolderItem.ExtendedProperty("{0CEF7D53-FA64-11D1-A203-0000F81FEDEE},6");
WScript.Echo(propVal);
}
}
I have 2 projects for which I am trying to create a generic Post-Build event batch file.
Here is the command in Visual Studio:
Post-Build event
if $(ConfigurationName) == Release ("$(ProjectDir)PostBuildRelease.bat" "$(TargetDir)" #(VersionNumber) "$(TargetFileName)" "$(TargetName)")
So I am calling the file PostBuildRelease.bat with 4 parameters:
Bin\Release Directory
Project Version
File Name With Extension
File Name Without Extension
Project 1
This works perfectly with this batch script:
CMD
SET parameter=%1 REM Full path to new bin\release\
SET parameter=%2 REM Full Version Number
SET parameter=%3 REM File name + extension
SET parameter=%4 REM File name - extension
SET "productionpath=Z:\Unused\Apps\LyncVdiChecker\"
MOVE %productionpath%%3 %productionpath%"_archive\"%4"."%DATE:~0,2%%DATE:~3,2%%DATE:~6,4%"-"%2
XCOPY %3 %productionpath%
Where the assembly is copied to Z:\Unused\Apps\LyncVdiChecker\ and the existing version copied to _archive in the same folder. The archived version also has the date and version number replace the file extension.
Project 2
This batch script also works perfectly (it does the same thing but in a different folder and for a different project):
CMD
SET parameter=%1 REM Full path to new bin\release\
SET parameter=%2 REM Full Version Number
SET parameter=%3 REM File name + extension
SET parameter=%4 REM File name - extension
SET "productionpath=Z:\Unused\Apps\IT Support App\"
MOVE "Z:\Unused\Apps\IT Support App\"%3 "Z:\Unused\Apps\IT Support App\_archive\"%4"."%DATE:~0,2%%DATE:~3,2%%DATE:~6,4%"-"%2
XCOPY %3 "Z:\Unused\Apps\IT Support App"
However, if I try using the same script from Project1 (the more generic version) in Project2, I get errors, even though the 2 scripts are equivalent:
Errors
The command "if Release == Release ("C:\Users\Seb.Kotze\Source\Repos\Applications\ITSelfHelp\ITHelp\PostBuildRelease.bat" "C:\Users\Seb.Kotze\Source\Repos\Applications\ITSelfHelp\ITHelp\bin\Release\" 2.0.6100.20905 "IT Self Help.exe" "IT Self Help")" exited with code 4.
Output Window:
The syntax of the command is incorrect.
Invalid number of parameters
This error is rather unhelpful, so I tried commenting out the 2 lines MOVE and XCOPY and build again:
Removed MOVE
Same error as above.
Output window:
Invalid number of parameters
Remove XCOPY
No Visual Studio Error, but this appears in the output window:
The syntax of the command is incorrect.
Parameter Output
When I echo out the parameters being used in Project2, everything seems to be in order:
"Path\to\Bin\Release"
2.0.6100.21082
"IT Self Help.exe"
"IT Self Help"
Z:\Unused\Apps\IT Support App\
How can I debug this issue? How is it possible that my script runs fine without any issues, but when run against a different project none of the commands are recognised? Any help with this is much appreciated!
You should normalize all your arguments, so they don't contain outer quotes.
Then you can use them in a reliable way.
The syntax set "variable=%~1" avoids outer quotes in the variable itself.
set "TargetDir=%~1"
set "VersionNumber=%~2"
set "TargetFileName=%~3"
set "TargetName=%~4"
SET "productionpath=Z:\IT Support App\"
set "dateStamp=%DATE:~0,2%%DATE:~3,2%%DATE:~6,4%"
MOVE "Z:\IT App\%TargetFileName%" "Z:\IT App\_archive\%TargetName%.%dateStamp%-%VersionNumber%"
XCOPY "%TargetFileName%" "Z:\IT App"
The problem is that the script is messing with the double quotes resulting in invalid paths and invalid number of arguments passed. When dealing with paths built dynamically, it's best to strip any existing " from the parts, and after the path is complete, surround it in ".
Dealing with batch arguments is explained on MSDN. Same thing for variables can be found on SS64.
I've played a bit with the file, and I was able to run it (from command line). The changes you should make in your (Project1) file:
SET productionpath="Z:\Unused\Apps\LyncVdiChecker\"
MOVE "%productionpath:"=%%~3" "%productionpath:"=%_archive\%~4.%DATE:~0,2%%DATE:~3,2%%DATE:~6,4%-%~2"
XCOPY "%~3" "%productionpath:"=%"
I moved the " from the productionpath line to the beginning of its contents. That way will work with paths that contain SPACE s.
In the MOVE and XCOPY lines, I did what I explained above: even if the syntax is not that clear, it's more robust (the last "%productionpath:"=%" could be simple written as %productionpath%, but I left it in the the 1st form for consistency).
Note: You could remove the CMD command at the beginning of your batch, since it starts a new cmd instance(process) that doesn't end.
I found a solution to this, but I am still not sure what the cause was.
I suspect it has something to do with either one of:
Spaces in productionpath causing the command parameter declaration to escape
Quotes around one or more of the parameters creating a non-existent file path
After trying out a few changes to the script, I found that changing the productionpath declaration to SET productionpath="Z:\Unused\Apps\IT Support App\" solved the issue:
CMD
SET parameter=%1 REM Full path to new bin\release\
SET parameter=%2 REM Full Version Number
SET parameter=%3 REM File name + extension
SET parameter=%4 REM File name - extension
SET productionpath="Z:\Unused\Apps\IT Support App\"
MOVE "Z:\Unused\Apps\IT Support App\"%3 "Z:\Unused\Apps\IT Support App\_archive\"%4"."%DATE:~0,2%%DATE:~3,2%%DATE:~6,4%"-"%2
XCOPY %3 "Z:\Unused\Apps\IT Support App"
Making the same change to the Project1 script did not cause that to break either, so this seems safe.
Update
After reading some of the other answers, I amended the script once again to the following:
CMD
SET "TargetDir=%~1"
SET "VersionNumber=%~2"
SET "TargetFileName=%~3"
SET "TargetName=%~4"
SET "ProductionPath=Z:\Unused\Apps\IT Support App\"
SET "ArchivePath=%ProductionPath%_archive\"
SET "DateStamp=%DATE:~0,2%%DATE:~3,2%%DATE:~6,4%"
MOVE "%ProductionPath%%TargetFileName%" "%ArchivePath%%TargetName%.%DateStamp%-%VersionNumber%"
XCOPY "%TargetFileName%" "%ProductionPath%"
Notice the "normalisation" of the paramaters - this removes all quotation marks from their values.
Also now using named parameters.
I'm trying to set the output folder of the compiled installer to the desktop.
This script can be runned by multiple people across multiple computers, that's why I need to use a dynamic script.
OutputDir= "{#Desktop}"
I'm able to use the prefix userdocs: but not userdesktop:.
//Works:
#define Path "userdocs:Visual Studio 2013\Projects\"
//Throws "Unknow filename prefix userdesktop:"
#define Desktop "userdesktop:";
Here is the documentation:
{userdesktop} & {commondesktop} *
The path to the desktop folder.
{userdocs} & {commondocs}
The path to the My Documents folder.
I also tried commomdesktop: with no success.
In that case you may want to use ISSI and its Constants.
#define ISSI_IncludePath "..\Inno Setup 5\ISSI\" ;path to ISSI
#include ISSI_IncludePath+"\_issi.isi"
[Setup]
OutputDir={#ISSI_myUserDesktop}
I'm trying to print all pdfs in current dir.
When I call this bash script in cmd (singlepdf.sh):
'"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe"' /t Gemeinde_348_BioID_842_alt.pdf everything's working fine.
When calling multiplepdfs.sh with this content:
declare -a pdfs=(*.pdf)
for pdf in ${pdfs[#]}; do
echo -e "\nprinting **$pdf** with AcroRd32.exe...\n"
'"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe"' /t $pdf
sleep 3
done
The echo shows that files are addressed correctly in the loop - but then I get the error "C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe": No such file or directory
Can someone help out with this issue?
Edit:
BTW, I have msys mingw installed
I know this is and old question, but i was faced with the same problem recently and none of the answers worked for me:
Couldn't find an old Foxit Reader version
As #pilkch said 2Printer adds a report page
Adobe Reader opens a gui
After searching a little more i found this: http://www.columbia.edu/~em36/pdftoprinter.html.
It's a simple exe that you call with the filename and it prints to the default printer (or one that you specify).
From the site:
PDFtoPrinter is a program for printing PDF files from the Windows command line. The program is designed generally for the Windows command line and also for use with the vDos DOS emulator.
To print a PDF file to the default Windows printer, use this command:
PDFtoPrinter.exe filename.pdf
To print to a specific printer, add the name of the printer in quotation marks:
PDFtoPrinter.exe filename.pdf "Name of Printer"
If you want to print to a network printer, use the name that appears in Windows print dialogs, like this (and be careful to note the two backslashes at the start of the name and the single backslash after the servername):
PDFtoPrinter.exe filename.pdf "\\SERVER\PrinterName"
I had two problems with using Acrobat Reader for this task.
The command line API is not officially supported, so it could change or be removed without warning.
Send a print command to Reader loads up the GUI, with seemingly no way to prevent it. I needed the process to be transparent to the user.
I stumbled across this blog, that suggests using Foxit Reader. Foxit Reader is free, the API is almost identical to Acrobat Reader, but crucially is documented and does not load the GUI for print jobs.
A word of warning, don't just click through the install process without paying attention, it tries to install unrelated software as well. Why are software vendors still doing this???
Looks like you are missing the printer name, driver, and port - in that order. Your final command should resemble:
AcroRd32.exe /t <file.pdf> <printer_name> <printer_driver> <printer_port>
For example:
"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" /t "C:\Folder\File.pdf" "Brother MFC-7820N USB Printer" "Brother MFC-7820N USB Printer" "IP_192.168.10.110"
Note: To find the printer information, right click your printer and choose properties. In my case shown above, the printer name and driver name matched - but your information may differ.
The error message is telling you.
Try just
"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe" /t "$pdf"
When you enclose the string in single-quotes, this makes everything inside a valid string, including the " chars. By removing the single-quotes, the shell will process the dbl-quotes as string "wrappers".
I would also wrap the filename variable in dbl-quotes so you can easily process files with spaces in their names, i.e.
"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe" /t "$pdf"
IHTH
I had the similar problem with printing multiple PDF files in a row and found only workaround by using 2Printer software.
Command line example to print PDF files:
2Printer.exe -s "C:\In\*.PDF" -prn "HP LasetJet 1100"
It is free for non-commercial use at http://doc2prn.com/
First response - wanted to finally give back to a helpful community...
Wanted to add this to the responses for people still looking for simple a solution. I'm using a free product by Foxit Software - FoxItReader.
Here is the link to the version that works with the silent print - newer versions the silent print feature is still not working.
FoxitReader623.815_Setup
FOR %%f IN (*.pdf) DO ("C:\Program Files (x86)\Foxit Software\Foxit Reader\FoxitReader.exe" /t %%f "SPST-SMPICK" %%f & del %%f)
I simply created a command to loop through the directory and for each pdf file (FOR %%f IN *.pdf) open the reader silently (/t) get the next PDF (%%f) and send it to the print queue (SPST-SMPICK), then delete each PDF after I send it to the print queue (del%%f). Shashank showed an example of moving the files to another directory if that what you need to do
FOR %%X in ("%dir1%*.pdf") DO (move "%%~dpnX.pdf" p/)
Using Acrobat reader is not a good solution, especially command line attributes are not documented. Additionally Acrobat reader's window stays open after printing process. PDF files are well known by printer drivers, so you may find better tools, like 2Printer.exe or RawFilePrinter.exe. In my opinion RawFilePrinter has better support and clear licencing process (you pay donation once and you can redistribute RawFilePrinter in many project you like - even new versions work with previously purchased license)
RawFilePrinter.exe -p "c:\Users\Me\Desktop\mypdffile.pdf" "Canon Printer"
IF %ERRORLEVEL% 1(
echo "Error!"
)
Latest version to download: http://bigdotsoftware.pl/index.php/rawfileprinter
The following batch script should achieve what you want. While it will leave an instance of Acrobat Reader running when finished, this will not cause any problems the next time this script is run.
#echo off
for %%f in (*.pdf) do (
echo Printing %cd%\%%f with Adobe Acrobat Reader...
start /b "Printing %%f" "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" /p /h "%cd%\%%f"
)
While you could separately kill the Acrobat Reader process afterwards there is the possibility this will close other PDF documents that are open that you didn't want closed.
Here is another solution:
1) Download SumatraPDF (portable version) - https://www.sumatrapdfreader.org/download-free-pdf-viewer.html
2) Create a class library project and unzip the SumatraPDF.exe to the project directory root and unblock it.
3) Inside the project Properties, go to the Resoruces tab and add the exe as a file.
4) Add the following class to your library:
public class SumatraWrapper : IDisposable
{
private readonly FileInfo _tempFileForExe = null;
private readonly FileInfo _exe = null;
public SumatraWrapper()
{
_exe = ExtractExe();
}
public SumatraWrapper(FileInfo tempFileForExe)
: this()
{
_tempFileForExe = tempFileForExe ?? throw new ArgumentNullException(nameof(tempFileForExe));
}
private FileInfo ExtractExe()
{
string tempfile =
_tempFileForExe != null ?
_tempFileForExe.FullName :
Path.GetTempFileName() + ".exe";
FileInfo exe = new FileInfo(tempfile);
byte[] bytes = Properties.Resources.SumatraPDF;
using (FileStream fs = exe.OpenWrite())
{
fs.Write(bytes, 0, bytes.Length);
}
return exe;
}
public bool Print(FileInfo file, string printerName)
{
string arguments = $"-print-to \"{printerName}\" \"{file.FullName}\"";
ProcessStartInfo processStartInfo = new ProcessStartInfo(_exe.FullName, arguments)
{
CreateNoWindow = true
};
using (Process process = Process.Start(processStartInfo))
{
process.WaitForExit();
return process.ExitCode == 0;
}
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
try
{
File.Delete(_exe.FullName);
}
catch
{
}
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
// ~PdfToPrinterWrapper() {
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
// }
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
5) Enjoy printing pdf files from your code.
Use like this:
FileInfo file = new FileInfo(#"c:\Sandbox\dummy file.pdf");
SumatraWrapper pdfToPrinter =
new SumatraWrapper();
pdfToPrinter.Print(file, "My Printer");
#ECHO off set "dir1=C:\TicketDownload"
FOR %%X in ("%dir1%*.pdf") DO ( "C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe" /t "%%~dpnX.pdf" "Microsoft XPS Document Writer" )
FOR %%X in ("%dir1%*.pdf") DO (move "%%~dpnX.pdf" p/)
Try this..May be u have some other version of Reader so that is the problem..
Today I was looking for this very solution and I tried PDFtoPrinter which I had an issue with (the PDFs I tried printing suggested they used incorrect paper size which hung the print job and nothing else printed until resolved). In my effort to find an alternative, I remembered GhostScript and utilities associated with it. I found
GSView and it's associated program GSPrint (reference https://www.ghostscript.com/). Both these require GhostScript (https://www.ghostscript.com/) but when all the components are installed, GSPrint worked flawlessly and I was able to create a scheduled task that printed PDFs automatically overnight.
Another solution "out of the box"
FOR %X in ("*.pdf") DO (C:\Windows\System32\print.exe /d:"\\printername" "%X.pdf")
Edit :
As mentionned by "huysentruitw", this only works for txt files ! Sorry !
When I double checked i realized I'm using GhostScript, as "Multiverse IT" proposed.
It looks like so :
"C:\Program Files (x86)\gs\gs\bin\gswin32c.exe" -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -sDEVICE=mswinpr2 -sOutputFile="%printer%My-Printer-Name" "c:\My-Pdf-File.pdf"