我們定製特殊的系統硬碟,就不需要,一遍遍的安裝驅動,軟體了,安裝好就是一個現成的模子。省時方便。
現在的大部分軟體,其安裝都具備一定的智能性,換句話說,許多軟體的安裝都能採取全自動或半自動的方式進行。
下面以不同的安裝方式進行討論:
1、基於 msi 包的 Windows Installer 安裝檔案:常用的靜默安裝參數為 /qb (顯示基本安裝介面)或 /q 或 /qn,若為了不重新啟動,還可以加上 REBOOT=SUPPRESS
如安裝虛擬光碟機 DaemonTools:msiexec /i dtools.msi /qb REBOOT=SUPPRESS
2、Windows 補丁包:有兩種情況,一種是類似 IE 增量補丁包的那種安裝檔案,要使之靜默安裝,只需要在執行檔案後加上 /q:a /r:n 參數即可;一種是 Windows 常用的補丁檔案,一般情況下加上 /U /N /Z 即可實現靜默安裝(對於新的系統補丁,也可使用 /passive /norestart)。這通用大部分情況,但某些特定的補丁不能用此法進行靜默安裝。
3、使用 InstallShield 製作的安裝檔案,可以使用如下命令列運行一遍安裝程式並獲得靜默安裝參數檔案 setup.iss:
setup.exe -r -f1:c:\setup.iss
然後將此 setup.iss 拷貝到安裝檔案目錄,並執行如下命令即可:setup.exe -s [-sms]
4、InstallShield with MSI 製作的安裝檔案,請使用類似:setup.exe /s /v"/qb" 來安裝
5、Wise InstallMaster 的安裝檔案,請使用:setup.exe /s
6、Inno Setup 製作的安裝檔案,請使用:setup.exe /sp- /silent /norestart
7、使用 NSIS (NullSoft Installation System) 製作的安裝檔案,可用 /S (注意大寫)來進行靜默安裝。樣本:setup.exe /S
8、Wise Installation Professional 製作的安裝檔案,可用 /silent 參數進行靜默安裝。
反正拿到一個安裝程式,大家用各靜默安裝參數試試就知道了([/s] [/S] [/silent [/noreboot]] [/verysilent [/sp-] [/norestart]] [/q] [/qn] [/qb] [REBOOT=SUPPRESS] [/s /v/qn] [/q:a /r:n] [/u /n /z] [/quiet] [/SilentInstallNoSponsor] [/SilentInstall] [/s /qn] [/s /qd] [-s] [-q] 等)
下面我們基於VC++實現XP的自動安裝與軟體的自動安裝
#include "stdafx.h"#include "addshell.h"#include "addshellDlg.h"#include "Shlwapi.h"#include "direct.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CAboutDlg dialog used for App Aboutclass CAboutDlg : public CDialog{public:CAboutDlg();// Dialog Data//{{AFX_DATA(CAboutDlg)enum { IDD = IDD_ABOUTBOX };//}}AFX_DATA// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CAboutDlg)protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support//}}AFX_VIRTUAL// Implementationprotected://{{AFX_MSG(CAboutDlg)//}}AFX_MSGDECLARE_MESSAGE_MAP()};//全域變數CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD){//{{AFX_DATA_INIT(CAboutDlg)//}}AFX_DATA_INIT}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAboutDlg)//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)//{{AFX_MSG_MAP(CAboutDlg)// No message handlers//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CAddshellDlg dialogCAddshellDlg::CAddshellDlg(CWnd* pParent /*=NULL*/): CDialog(CAddshellDlg::IDD, pParent){//{{AFX_DATA_INIT(CAddshellDlg)m_FilePathName = _T("");m_CatalogName = _T("");//}}AFX_DATA_INIT// Note that LoadIcon does not require a subsequent DestroyIcon in Win32m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CAddshellDlg::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CAddshellDlg)DDX_Control(pDX, IDC_RICHEDIT_PROCINFO, m_RichEditProcInfo);DDX_Text(pDX, IDC_EDIT_FILEPATHNAME, m_FilePathName);DDX_Text(pDX, IDC_EDIT_CATALOG, m_CatalogName);//}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAddshellDlg, CDialog)//{{AFX_MSG_MAP(CAddshellDlg)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON_OPENFILE, OnButtonOpenfile)ON_BN_CLICKED(IDC_BUTTON_PACKING, OnButtonPacking)ON_BN_CLICKED(IDC_BUTTON1, OnButtonOpenCatalog)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CAddshellDlg message handlersBOOL CAddshellDlg::OnInitDialog(){CDialog::OnInitDialog();// Add "About..." menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// Set the icon for this dialog. The framework does this automatically// when the application's main window is not a dialogSetIcon(m_hIcon, TRUE);// Set big iconSetIcon(m_hIcon, FALSE);// Set small icon// TODO: Add extra initialization herereturn TRUE; // return TRUE unless you set the focus to a control}void CAddshellDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// If you add a minimize button to your dialog, you will need the code below// to draw the icon. For MFC applications using the document/view model,// this is automatically done for you by the framework.void CAddshellDlg::OnPaint() {if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);// Center icon in client rectangleint cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// Draw the icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}// The system calls this to obtain the cursor to display while the user drags// the minimized window.HCURSOR CAddshellDlg::OnQueryDragIcon(){return (HCURSOR) m_hIcon;}void CAddshellDlg::OnButtonOpenfile() {// TODO: Add your control notification handler code here//設定檔案過濾,預設開啟哪些檔案類型,最後“||”結束。 char szFilter[]="可執行檔(*.exe)|*.exe|全部檔案(*.*)|*.*||"; //通過查閱MSDN,瞭解CFileDialog中建構函式的用法。 //第一個參數為TRUE,表示開啟檔案對話方塊;為FALSE,表示儲存對話方塊。 //其他詳細參數說明見後面。 CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL); //通過模態對話方塊顯示檔案對話方塊 if (dlg.DoModal()==IDOK){ //擷取檔案路徑 m_FilePathName=dlg.GetPathName(); //設定RICHEDIT內容 //將指標設定到編輯框最後 m_RichEditProcInfo.SetSel(-1,-1); //替換編輯框最後的內容,實際上就是在最後新增內容。 m_RichEditProcInfo.ReplaceSel("檔案路徑:"); m_RichEditProcInfo.ReplaceSel(m_FilePathName); m_RichEditProcInfo.ReplaceSel("\r\n"); //用擷取的檔案路徑更新編輯框內容。 UpdateData(FALSE);}}void CAddshellDlg::OnButtonPacking() {//獲得目前的目錄CString path_directory,path_txt; //path_directory:路徑 path_txt:路徑+檔案名稱 GetModuleFileName(NULL,path_txt.GetBuffer(MAX_PATH),MAX_PATH); //得到當前執行程式的路徑 path_txt.ReleaseBuffer(); int path_directory_length = path_txt.ReverseFind('\\'); path_directory = path_txt.Left(path_directory_length + 1);//獲得WINNT.sif檔案路徑char SIFFilePath[255];strcpy(SIFFilePath,path_directory);strcat(SIFFilePath,"WINNT.sif");if (!PathFileExists(SIFFilePath)){MessageBox("WINNT.sif不在該程式的目錄中","注意",MB_OK);return;}//建立$OEM$\$1\install\目錄char InstallPath[255];char AppCMDPath[255];strcpy(InstallPath,m_CatalogName);strcat(InstallPath,"\\$OEM{1}quot;);CreateDirectory(InstallPath,NULL); strcat(InstallPath,"\\$1");CreateDirectory(InstallPath,NULL);strcat(InstallPath,"\\install"); CreateDirectory(InstallPath,NULL);strcpy(AppCMDPath,InstallPath);strcat(AppCMDPath,"\\applications.cmd");strcat(InstallPath,"\\applications"); CreateDirectory(InstallPath,NULL);strcat(InstallPath,"\\RunSoft.exe");CopyFile(m_FilePathName,InstallPath,FALSE);if (!PathFileExists(InstallPath)){MessageBox("EXE檔案拷貝失敗","注意",MB_OK);return;}//設定RICHEDIT內容 //將指標設定到編輯框最後 m_RichEditProcInfo.SetSel(-1,-1); //替換編輯框最後的內容,實際上就是在最後新增內容。 m_RichEditProcInfo.ReplaceSel("可執行檔拷貝完成: "); m_RichEditProcInfo.ReplaceSel(InstallPath);m_RichEditProcInfo.ReplaceSel("\r\n"); //用擷取的檔案路徑更新編輯框內容。 UpdateData(FALSE);//建立applications.cmd檔案FILE *AppCMDFile;if((AppCMDFile = fopen(AppCMDPath,"wt+")) == NULL) //文字檔,允許讀寫{MessageBox("Applications.cmd檔案建立失敗","注意",MB_OK);}fseek(AppCMDFile,0L,SEEK_SET);fputs("CLS\r\n",AppCMDFile);fputs("@echo off\r\n",AppCMDFile);fputs("start /wait %systemdrive%\\install\\applications\\RunSoft.exe\r\n",AppCMDFile);fputs("RD /S /Q %systemdrive%\\install\r\n",AppCMDFile);fputs("EXIT",AppCMDFile);fclose(AppCMDFile);//設定RICHEDIT內容 //將指標設定到編輯框最後 m_RichEditProcInfo.SetSel(-1,-1); //替換編輯框最後的內容,實際上就是在最後新增內容。 m_RichEditProcInfo.ReplaceSel("Applications.cmd檔案建立完成: "); m_RichEditProcInfo.ReplaceSel(AppCMDPath);m_RichEditProcInfo.ReplaceSel("\r\n"); //用擷取的檔案路徑更新編輯框內容。 UpdateData(FALSE); //exe檔案拷貝完成//開始拷貝winnt.sif檔案char SIFI386Path[255] ={0};strcpy(SIFI386Path,m_CatalogName);strcat(SIFI386Path,"\\I386\\WINNT.sif");CopyFile(SIFFilePath,SIFI386Path,FALSE);if (!PathFileExists(SIFI386Path)){MessageBox("WINNT.sif檔案拷貝失敗","注意",MB_OK);return;}//將要啟動並執行檔案路徑加入WINNT.sif檔案FILE *SIFFile;if((SIFFile = fopen(SIFI386Path,"at+")) == NULL) //文字檔,允許讀和追加{MessageBox("WINNT.sif檔案追加開啟失敗","注意",MB_OK);}fseek(SIFFile,0L,SEEK_END);fputs("\r\n",SIFFile);fputs("[GuiRunOnce]\r\n",SIFFile);fputs("%systemdrive%\\install\\applications.cmd\r\n",SIFFile);fclose(SIFFile);//設定RICHEDIT內容 //將指標設定到編輯框最後 m_RichEditProcInfo.SetSel(-1,-1); //替換編輯框最後的內容,實際上就是在最後新增內容。 m_RichEditProcInfo.ReplaceSel("WINNT.sif檔案設定完成,可以打包");m_RichEditProcInfo.ReplaceSel("\r\n"); //用擷取的檔案路徑更新編輯框內容。 UpdateData(FALSE);}void CAddshellDlg::OnButtonOpenCatalog() { char szDir[255]; BROWSEINFO bi; ITEMIDLIST *pidl; bi.hwndOwner = this->m_hWnd; bi.pidlRoot = NULL; bi.pszDisplayName = szDir; bi.lpszTitle = "選擇要添加的檔案夾"; bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_DONTGOBELOWDOMAIN; bi.lpfn = NULL; bi.lParam = 0; bi.iImage = 0; pidl = SHBrowseForFolder(&bi); if(pidl == NULL) return; SHGetPathFromIDList(pidl, szDir); m_CatalogName=szDir;//判斷輸入的目錄是否存在 if (!PathFileExists(szDir)){MessageBox("目錄不存在","注意",MB_OK);return;}char I386String[255];strcpy(I386String,m_CatalogName);strcat(I386String,"\\i386"); if (!PathFileExists(I386String)){MessageBox("I386目錄不存在","注意",MB_OK);return;} //設定RICHEDIT內容 //將指標設定到編輯框最後 m_RichEditProcInfo.SetSel(-1,-1); //替換編輯框最後的內容,實際上就是在最後新增內容。 m_RichEditProcInfo.ReplaceSel("系統檔案目錄:"); m_RichEditProcInfo.ReplaceSel(m_CatalogName);m_RichEditProcInfo.ReplaceSel("\r\n"); //用擷取的檔案路徑更新編輯框內容。 UpdateData(FALSE);}