C# DEVCON.EXE(驱动程序工具)和OpenVPN
我们已经编写了一个应用程序,作为一个更大软件包的附加组件,从托盘中管理OpenVPN OpenVPN包含一个名为tapinstall.exe的文件,用于安装OpenVPN适配器(或任何驱动程序)。进行一些研究后,该文件与Microsoft在WindowsDDK中包含的名为devcon的命令行工具完全相同。OpenVPN的人只是为了使用而重命名了它 因此,我们在安装程序(msi)的过程中,通过自定义操作使用它来安装驱动程序,在大多数情况下,它工作正常 devcon时不时地会失败并挂起——永远不会退出。之后,您可以重新运行devcon,它将安装驱动程序两次。。。这基本上破坏了OpenVPN 有没有人见过devcon的这个问题,知道它在做什么,或者知道解决它的方法 作为替代解决方案,有人知道如何从C#安装驱动程序吗?(我们有一个.inf和一个.sys文件) 更新:我们发现这种问题非常罕见。当我们应用了一个更新,卸载V8版本的OpenVPN适配器,然后安装新版本(V9)的OpenVPN适配器时,这种情况最常见。如果在安装之间重新启动电脑,这似乎也不会发生,因此我们最好在卸载时强制重新启动电脑C# DEVCON.EXE(驱动程序工具)和OpenVPN,c#,driver,openvpn,C#,Driver,Openvpn,我们已经编写了一个应用程序,作为一个更大软件包的附加组件,从托盘中管理OpenVPN OpenVPN包含一个名为tapinstall.exe的文件,用于安装OpenVPN适配器(或任何驱动程序)。进行一些研究后,该文件与Microsoft在WindowsDDK中包含的名为devcon的命令行工具完全相同。OpenVPN的人只是为了使用而重命名了它 因此,我们在安装程序(msi)的过程中,通过自定义操作使用它来安装驱动程序,在大多数情况下,它工作正常 devcon时不时地会失败并挂起——永远不会退
旁注:我听说有人使用WiX和DifxAPI(我想这就是它的名字)从MSI安装程序安装驱动程序。如果这可以在自定义操作中从普通C#实现,有什么想法吗?我们真的不想使用WiX重新开始安装项目(这可能很耗时)。我没有解决您问题的方法,但这里有一些想法:
- DevCon的源代码作为DDK root\Src\Setup\DevCon下的一部分提供。如果您的问题是可复制的,您可以构建自己的版本并在IDE中进行调试
- 可以在中找到OpenVPN安装程序的源代码。您可以比较DevCon是如何被调用的,并查看OpenVPN是否以防止问题发生的方式进行调用
- 可以使用以下命令行安装INF文件
但我猜DevCon做的不止这些,所以我不知道这是否是一种可行的方法。OpenVPN安装程序使用DevCon显然是有原因的,对吧rundll32 syssetup,SetupInfObjectInstallAction DefaultInstall 128.\.inf
@更新: OpenVPN安装程序似乎取决于DevCon的返回值
;------------------------------------------
;Set reboot flag based on tapinstall return
Function CheckReboot
IntCmp $R0 1 "" noreboot noreboot
IntOp $R0 0 & 0
SetRebootFlag true
DetailPrint "REBOOT flag set"
noreboot:
FunctionEnd
@旁注: 我想您应该能够使用p/Invokes将DevCon移植到C。DevCon显然只是一个包装器和DIFxAPI
DIFxAPI 文件:
SetDifxLogCallback(DIFLogCallbackFunc, IntPtr.Zero);
bool needReboot;
var error =
DriverPackageInstall(driverPackageInfPath, 0, IntPtr.Zero, out needReboot);
if (error != 0)
throw new Win32Exception(error);
输出:
INFO: ENTER: DriverPackageInstallW. Error code: 0
INFO: Installing INF file 'C:\Program Files (x86)\OpenVPN\driver\OemWin2k.inf' (Plug and Play).. Error code: 0
INFO: Looking for Model Section [tap0901.NTamd64].... Error code: 0
INFO: Installing devices with Id "tap0901" using INF "C:\Windows\system32\DriverStore\FileRepository\oemwin2k.inf_128556d6\OemWin2k.inf".. Error code: 0
INFO: ENTER UpdateDriverForPlugAndPlayDevices.... Error code: 0
SUCCESS: RETURN UpdateDriverForPlugAndPlayDevices.. Error code: 0
INFO: Installation was successful.. Error code: 0
SUCCESS: Install completed. Error code: 0
INFO: RETURN: DriverPackageInstallW (0x0). Error code: 0
该程序必须以管理员身份运行,否则会出现错误\u访问被拒绝
如果驱动程序已经安装,您将得到一个
错误\u NO\u MORE\u ITEMS
只是一个补充,如果有人无法运行difxapi函数,您需要通过某种方式将项目链接到WDK附带的difxapi.h
和difxapi.lib
快速方式,只需将difxapi.h
和difxapi.lib
复制到您的文件夹项目并添加到您的项目中。请注意,选择的文件与wdk文件夹中的x86兼容
一个简单的代码示例,仅用于测试,使用在win 7 32位上运行的C:
#include <windows.h>
#include <stdio.h>
#include "difxapi.h"
int main(void)
{
DWORD dwRet = 0;
PCTSTR DriverPackageInfPath = TEXT("D:\\MYDRIVER.INF");
DWORD Flags = 0;
INSTALLERINFO InstallerInfo;
BOOL bNeedReboot;
char chName[] = "Thing Name";
char chGUID[] = "{4D36E979-E325-11CE-BFC1-08002BE10318}"; //printer GUID
InstallerInfo.pDisplayName = &chName;
InstallerInfo.pProductName = &chName;
InstallerInfo.pMfgName = &chName;
InstallerInfo.pApplicationId = &chGUID;
dwRet = DriverPackageInstall( DriverPackageInfPath, Flags, &InstallerInfo , &bNeedReboot );
switch(dwRet)
{
case ERROR_SUCCESS:
printf("\n\n ERROR_SUCCESS - Ret: %d, %xh", dwRet, dwRet);
break;
case CERT_E_EXPIRED:
printf("\n\n CERT_E_EXPIRED - Ret: %d, %xh", dwRet, dwRet);
break;
case CERT_E_UNTRUSTEDROOT:
printf("\n\n CERT_E_UNTRUSTEDROOT - Ret: %d, %xh", dwRet, dwRet);
break;
case CERT_E_WRONG_USAGE:
printf("\n\n CERT_E_WRONG_USAGE - Ret: %d, %xh", dwRet, dwRet);
break;
case CRYPT_E_FILE_ERROR:
printf("\n\n CRYPT_E_FILE_ERROR - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_ACCESS_DENIED:
printf("\n\n ERROR_ACCESS_DENIED - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_BAD_ENVIRONMENT:
printf("\n\n ERROR_BAD_ENVIRONMENT - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_CANT_ACCESS_FILE:
printf("\n\n ERROR_CANT_ACCESS_FILE - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_FILE_NOT_FOUND:
printf("\n\n ERROR_FILE_NOT_FOUND - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_FILENAME_EXCED_RANGE:
printf("\n\n ERROR_FILENAME_EXCED_RANGE - Ret: %d, %xh", dwRet, dwRet);
break;
/*case ERROR_IN_WOW64:
printf("\n\n ERROR_IN_WOW64 - Ret: %d, %xh", dwRet, dwRet);
break;*/
case ERROR_INSTALL_FAILURE:
printf("\n\n ERROR_INSTALL_FAILURE - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_INVALID_CATALOG_DATA:
printf("\n\n ERROR_INVALID_CATALOG_DATA - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_INVALID_NAME:
printf("\n\n ERROR_INVALID_NAME - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_INVALID_PARAMETER:
printf("\n\n ERROR_INVALID_PARAMETER - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_NO_DEVICE_ID:
printf("\n\n ERROR_NO_DEVICE_ID - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_NO_MORE_ITEMS:
printf("\n\n ERROR_NO_MORE_ITEMS - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_NO_SUCH_DEVINST:
printf("\n\n ERROR_NO_SUCH_DEVINST - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_OUTOFMEMORY:
printf("\n\n ERROR_OUTOFMEMORY - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_SHARING_VIOLATION:
printf("\n\n ERROR_SHARING_VIOLATION - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH:
printf("\n\n ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH - Ret: %d, %xh", dwRet, dwRet);
break;
case ERROR_UNSUPPORTED_TYPE:
printf("\n\n ERROR_UNSUPPORTED_TYPE - Ret: %d, %xh", dwRet, dwRet);
break;
case TRUST_E_NOSIGNATURE:
printf("\n\n TRUST_E_NOSIGNATURE - Ret: %d, %xh", dwRet, dwRet);
break;
default:
printf("\n\n default - Ret: %d, %xh", dwRet, dwRet);
break;
}
printf("\n\n");
system("pause");
return 1;
}
#包括
#包括
#包括“difxapi.h”
内部主(空)
{
DWORD dwRet=0;
PCTSTR DriverPackageInfPath=TEXT(“D:\\MYDRIVER.INF”);
DWORD标志=0;
INSTALLERINFO INSTALLERINFO;
BOOL-bNeedReboot;
char chName[]=“事物名称”;
char chGUID[]=“{4D36E979-E325-11CE-BFC1-08002BE10318}”;//打印机GUID
InstallerInfo.pDisplayName=&chName;
InstallerInfo.pProductName=&chName;
InstallerInfo.pMfgName=&chName;
InstallerInfo.pApplicationId=&chGUID;
dwRet=DriverPackageInstall(DriverPackageInfPath、Flags、&installernfo、&bNeedReboot);
交换机(dwRet)
{
案例错误\u成功:
printf(“\n\n错误\u成功-Ret:%d,%xh”,dwRet,dwRet);
打破
案例证书已过期:
printf(“\n\n证书已过期-Ret:%d,%xh”,dwRet,dwRet);
打破
案例证书不可信:
printf(“\n\n证书不可信-Ret:%d,%xh”,dwRet,dwRet);
打破
案例证书错误使用:
printf(“\n\n证书使用错误-Ret:%d,%xh”,dwRet,dwRet);
打破
案例加密文件错误:
printf(“\n\n加密文件错误-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u访问\u被拒绝:
printf(“\n\n错误\u访问被拒绝-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u坏\u环境:
printf(“\n\n错误\u坏\u环境-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u无法\u访问\u文件:
printf(“\n\n错误\u无法\u访问\u文件-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u未找到文件\u:
printf(“\n\n找不到错误文件-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u文件名\u超出\u范围:
printf(“\n\n错误\u文件名\u超出\u范围-Ret:%d,%xh”,dwRet,dwRet);
打破
/*案例错误\u在\u WOW64中:
printf(“\n\n错误\u在\u WOW64-Ret:%d,%xh”,dwRet,dwRet);
中断*/
案例错误\u安装\u失败:
printf(“\n\n错误\u安装\u失败-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u无效\u目录\u数据:
printf(“\n\n错误\u无效\u目录\u数据-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u无效\u名称:
printf(“\n\n错误\u无效\u名称-Ret:%d,%xh”,dwRet,dwRet);
打破
案例错误\u无效\u参数:
printf(“\n\n错误\u无效\u参数-Ret:%d,%xh”,dwRet,dwRet);
布雷亚