Window安装程序在单个快捷方式图标上运行两个exe

时间:2017-06-12 04:35:27

标签: windows batch-file windows-installer

我有两个应该一起运行的.exe文件,否则我的应用程序将无法运行。所以我创建了一个批处理脚本,它可以运行两个exe,最终它的批处理窗口文件不是窗口安装程序。

我查看了其他打包工具Inno,但他们没有执行两项并行操作。

无论如何,我可以从窗口运行两个带有单个快捷图标的exe文件吗?如果你能提供一点帮助,我将不胜感激。 提前谢谢。

2 个答案:

答案 0 :(得分:2)

如果我不误解你......

这是一个生成.Net exe的批处理文件,可以根据需要启动任意数量的进程。保存为(即 build.bat )运行它,您将获得一个myNetExe.exe文件,该文件将启动两个notepad

//>nul 2>nul||@goto :batch_code
/*
:batch_code
@echo off
setlocal
rem place desired exe name
set "theExeFile=myNetExe.exe"
rem if not exist "%theExeFile%" call :build_the_exe || exit/B
call :build_the_exe || exit/B

endlocal
exit /b 0

:build_the_exe
:: find csc.exe
set "frm=%SystemRoot%\Microsoft.NET\Framework\"
for /f "tokens=* delims=" %%v in ('dir /b /a:d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
   set netver=%%v
   goto :break_loop
)
:break_loop
set "csc=%frm%%netver%\csc.exe"
:: csc not found
if "%csc%" == "\csc.exe" echo/&echo/Warning: Net Framework Not Found&exit/B 1
::csc found
call %csc% /nologo /out:"%theExeFile%" "%~dpsfnx0" 
exit/B 0
*/

//begin c# code

using System;
using System.Security;                // get secure string
using System.Diagnostics;             // processes

namespace ElZooilogico
{

  public class Procesos
  {
    private static SecureString GetSecureString(string str)
    {
      SecureString secureString = new SecureString();
      foreach (char ch in str)
      {
        secureString.AppendChar(ch);
      }
      secureString.MakeReadOnly();
      return secureString;
    }

    //public static bool CreateProceso(string processName, string processArgs, string user, string pass, out uint processID, bool bShowWindow = true)
    public static bool CreateProceso(string processName, string processArgs, out uint processID, bool bShowWindow = true)
    {
      bool result = false;
      processID   = 0;

      try
      {
        ProcessStartInfo procStartInfo = new ProcessStartInfo()
        {
          RedirectStandardOutput = false,
          UseShellExecute = false,
          CreateNoWindow = bShowWindow,
          //UserName = user,
          //Password = GetSecureString(pass),
          FileName = processName,
          Arguments = processArgs
        };

        Process p = new Process();
        p.StartInfo = procStartInfo;

        if ( (result = p.Start()) )
          processID = (uint)p.Id;
      } catch {}
      return result;
    }

    public static void Main()
    {
      uint processID = 0;
      try {
        CreateProceso("notepad", @"C:\Windows\win.ini", out processID, true);
        CreateProceso("notepad", @"C:\Windows\system.ini", out processID, true);

        //use following line to start process under other user account (remove comments from UserName/Password above)
        //CreateProceso("notepad", @"C:\Windows\win.ini", "some_user_name", "user_password", out processID, true);
      } catch {}
    }

  } // class Procesos

}

使用notepadpath\exeC:\Windows\win.ini更改为您的参数并将其更改为

此外,您可以更改main函数以从命令行运行程序,但是您必须确保始终为每个程序设置一对program + prog_params。另外,如果pathparams包含空格,请加上引号。另一种方法是添加检查,但不在此范围内。

即。 myNetExe "C:\Program Files (x86)\some_folder\some.exe" "param1 param2" "C:\Program Files (x86)\some_other_folder\other.exe" ""。在后面,没有参数,但必须发送空字符串。

public static void Main(string[] args)
{
  uint processID = 0;
  try {
    for ( int i = 0; i < args.Length; i+=2 )
    {
      CreateProceso(args[i], args[i+1], out processID, true);
    }
  } catch {}
}

编辑仅作为概念验证,添加了用于创建快捷方式的开关。

//>nul 2>nul||@goto :batch_code
/*
:batch_code
@echo off
setlocal
rem place desired exe name
set "theExeFile=myNetExe.exe"
rem if not exist "%theExeFile%" call :build_the_exe || exit/B
call :build_the_exe || exit/B

endlocal
exit /b 0

:build_the_exe
:: find csc.exe
set "frm=%SystemRoot%\Microsoft.NET\Framework\"
for /f "tokens=* delims=" %%v in ('dir /b /a:d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
   set netver=%%v
   goto :break_loop
)
:break_loop
rem set "netver=v3.5" & rem for version build testing purposes
cls&echo/&echo/Framework version is [%netver:~1%]&echo/
set "csc=%frm%%netver%\csc.exe"
:: csc not found
if "%csc%" == "\csc.exe" echo/&echo/Warning: Net Framework Not Found&exit/B 1
::csc found
if /I "%netver%" EQU "v3.5" (
  call %csc% /nologo /define:NET35 /out:"%theExeFile%" "%~dpsfnx0" && (echo Done^!) || (echo Failed^!)
) else (
  call %csc% /nologo /define:NET40 /out:"%theExeFile%" "%~dpsfnx0" && (echo Done^!) || (echo Failed^!)
)
exit/B 0
*/



//begin c# code
using System;
using System.IO;                      // file, path
using System.Security;                // get secure string
using System.Reflection;              // Shortcut
using System.Diagnostics;             // processes
using System.Windows.Forms;           // Application
using System.Runtime.InteropServices; // Com

namespace ElZooilogico
{
  public static class Shortcut
  {
    private const string DEFAULT_EXTENSION  = ".lnk";

#if (NET35)
    public static string Create(string linkFileName, string targetPath, string description, string arguments, int iconNumber)
#else
    public static string Create(string linkFileName, string targetPath, string description = "", string arguments = "", int iconNumber = 0)
#endif
    {
      if ( linkFileName.Contains(DEFAULT_EXTENSION) == false )
        linkFileName = string.Format("{0}{1}", linkFileName, DEFAULT_EXTENSION);

      if ( File.Exists(targetPath) == false )
        throw new Exception(targetPath);

      string iconLocation = string.Format("{0},{1}", targetPath, iconNumber);

      Type t = Type.GetTypeFromCLSID(new Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8")); //Windows Script Host Shell Object

#if (NET35)
      object shell = Activator.CreateInstance(t);
      try {
        object shortcut = t.InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shell, new object[]{linkFileName});
        try {
          t.InvokeMember("TargetPath", BindingFlags.SetProperty, null, shortcut, new object[]{targetPath});
          t.InvokeMember("WorkingDirectory", BindingFlags.SetProperty, null, shortcut, new object[]{Path.GetDirectoryName(targetPath)});
          t.InvokeMember("Arguments", BindingFlags.SetProperty, null, shortcut, new object[]{arguments});
          t.InvokeMember("WindowStyle", BindingFlags.SetProperty, null, shortcut, new object[]{1});
          t.InvokeMember("Description", BindingFlags.SetProperty, null, shortcut, new object[]{description});
          t.InvokeMember("IconLocation", BindingFlags.SetProperty, null, shortcut, new object[]{"shell32.dll, 5"});
          t.InvokeMember("Save", BindingFlags.InvokeMethod, null, shortcut, null);
        } finally { Marshal.FinalReleaseComObject(shortcut); }
      } finally { Marshal.FinalReleaseComObject(shell); }
#else
      dynamic shell = Activator.CreateInstance(t);
      try {
        var shortcut = shell.CreateShortcut(linkFileName);
        try {
          shortcut.TargetPath = targetPath;
          shortcut.WorkingDirectory = Path.GetDirectoryName(targetPath);
          shortcut.Arguments = arguments;
          shortcut.WindowStyle = 1;
          shortcut.Description = description;
          shortcut.IconLocation = "shell32.dll, 1"; //iconLocation; // "shell32.dll, 1";
          shortcut.Save();
        } finally { Marshal.FinalReleaseComObject(shortcut); }
      } finally { Marshal.FinalReleaseComObject(shell); }
#endif
      return Path.Combine(System.Windows.Forms.Application.StartupPath, linkFileName);
    }

  } // class Shortcut



  public class Procesos
  {
    private static string own = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\My Shortcut";
#if (NET35)
    private static string all = Path.GetPathRoot(Environment.SystemDirectory) + @"Users\Public\Desktop\All Shortcut";
#else
    private static string all = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory) + "\\All Shortcut";
#endif

    private static SecureString GetSecureString(string str)
    {
      SecureString secureString = new SecureString();
      foreach (char ch in str)
      {
        secureString.AppendChar(ch);
      }
      secureString.MakeReadOnly();
      return secureString;
    }

    //public static bool CreateProceso(string processName, string processArgs, string user, string pass, out uint processID, bool bShowWindow = true)
#if (NET35)
    public static bool CreateProceso(string processName, string processArgs, out uint processID, bool bShowWindow)
#else
    public static bool CreateProceso(string processName, string processArgs, out uint processID, bool bShowWindow = true)
#endif
    {
      bool result = false;
      processID   = 0;

      try
      {
        ProcessStartInfo procStartInfo = new ProcessStartInfo()
        {
          RedirectStandardOutput = false,
          UseShellExecute = false,
          CreateNoWindow = bShowWindow,
          //UserName = user,
          //Password = GetSecureString(pass),
          FileName = processName,
          Arguments = processArgs
        };

        Process p = new Process();
        p.StartInfo = procStartInfo;

        if ( (result = p.Start()) )
          processID = (uint)p.Id;
      } catch {}
      return result;
    }

    public static void Main(string[] args)
    {
      uint processID = 0;

      if ( args.Length > 0 )
      {
        try {
          for ( int i = 0; i < args.Length; i+=2 )
          {
            if ( args[i].Equals("/LO", StringComparison.OrdinalIgnoreCase) ) { try { Shortcut.Create(own, Application.ExecutablePath, "This is a shortcut for current user", string.Empty, 0); } catch (Exception e) { MessageBox.Show(e.Message); return; } return; }
            if ( args[i].Equals("/LA", StringComparison.OrdinalIgnoreCase) ) { try { Shortcut.Create(all, Application.ExecutablePath, "This is a shortcut for all users", string.Empty, 0); } catch (Exception e) { MessageBox.Show(e.Message); return; } return; }
            try
            {
              CreateProceso(args[i], args[i+1], out processID, true);
            } catch {}
          }
         } catch {}
      }
      else
      {
        try {
          CreateProceso("notepad", @"C:\Windows\win.ini", out processID, true);
          CreateProceso("notepad", @"C:\Windows\system.ini", out processID, true);
          //use following line to start process under other user account (remove comments from UserName/Password above)
          //CreateProceso("notepad", @"C:\Windows\win.ini", "some_user_name", "user_password", out processID, true);
        } catch {}
      }
    }
  } // class Procesos
} // namespace ElZooilogico

答案 1 :(得分:0)

Inno Setup解决了这个问题,我经历了几个自己的脚本,它根据它的命令行事。这是 setup.iss 有效的解决方案:

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

[Setup]
AppName=Electron
AppVersion=1.5
DefaultDirName={pf}\MySetup
DefaultGroupName=MySetup
UninstallDisplayIcon={app}\MySetup.exe
Compression=lzma2
SolidCompression=yes
OutputDir=userdocs:Inno Setup Examples Output

[Files]
 Source: "D:\FirstExeFolder\*"; DestDir: "{app}\App"; Flags: ignoreversion recursesubdirs
 Source: "D:\test\SecondExeFolder\*"; DestDir: "{app}\server"; Flags: ignoreversion recursesubdirs
 Source: "D:\test\batinstaller.bat"; DestDir: "{app}"

[Icons]
Name: "{group}\MySetup"; Filename: "{app}\batinstaller.bat"; WorkingDir: "{app}"; IconFilename: "{app}\icon.ico" 


[Run]
Filename: "{app}\batinstaller.bat" 

它会将脚本编译成窗口安装程序,可以在任何窗口机器中支持。