我正在开发一个需要在Windows 7 PC上激活Windows的项目。我使用Windows软件许可API编写了下面的代码。 MSDN说下面使用的三个函数需要Windows 8或Windows Server 2012,这表明这些函数在Windows 7上不可用。但是如果我打开了在我的C:\ Windows \ System32中的depends.exe中的slc.dll Windows 7机器,我做SLOpen和SLClose功能。但不是SLActivateProduct。
当我构建程序时,我收到链接器错误:
1> main.cpp
1>main.obj : error LNK2019: unresolved external symbol _SLActivateProduct@28 referenced in function _main
1>activate_windows.exe : fatal error LNK1120: 1 unresolved externals
这在链接时如何工作?我认为这意味着slc.lib(见下面的代码)没有SLActivateProduct函数?
这个程序不需要用C语言编写,所以我可以从脚本中调用任何东西。任何人都知道在Windows 7上是否有任何方法可以做到这一点?它必须是一种可以通过运行脚本来启动的编程方式。
以下代码:
#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <stdio.h>
// lib to use
#pragma comment(lib, "slc.lib")
int main() {
// slmgr.vbs has:
// private const WindowsAppId = "55c92734-d682-4d71-983e-d6ec3f16059f"
// Windows AppId for SLID: {55c92734-d682-4d71-983e-d6ec3f16059f} - this is a GUID
const SLID SLID_WINDOWS = {0x55c92734, 0xd682, 0x4d71, 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f};
HSLC hslc;
HRESULT hr = SLOpen(&hslc);
if (SUCCEEDED(hr))
{
// try to activate windows
hr = SLActivateProduct(hslc, &SLID_WINDOWS, 0, NULL, NULL, NULL, 0);
switch(hr) {
case E_INVALIDARG:
printf("SLActivateProduct - one or more arguments are not valid\n");
break;
case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case SL_E_PKEY_NOT_INSTALLED:
printf("SLActivateProduct - The product key is not available\n");
break;
case SL_E_PRODUCT_SKU_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case S_OK:
printf("SLActivateProduct - returned S_OK\n");
break;
default:
printf("SLActivateProduct - unknown return code\n");
break;
}
hr=SLClose(hslc);
}
}
答案 0 :(得分:2)
SLActivateProduct()
在Windows 7上根本不可用,即使您可以在编译时链接到它(显然您不能,因为您的slc.lib
版本缺少该引用)。
但是,您可以使用SLActivateProduct()
在运行时动态加载GetProcAddress()
。这将使您超越链接器错误(直到您更新开发环境)并允许您的代码至少在Windows 8及更高版本上运行。
仅供参考,sliddefs.h
定义WINDOWS_SLID
常量,因此您无需在代码中手动定义它。
尝试更像这样的事情:
#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <sliddefs.h>
#include <stdio.h>
// lib to use
#pragma comment(lib, "slc.lib")
// if your version of Slpublic.h does not define these then uncomment this...
/*
typedef enum _tagSL_ACTIVATION_TYPE {
SL_ACTIVATION_TYPE_DEFAULT = 0,
SL_ACTIVATION_TYPE_ACTIVE_DIRECTORY = 1
} SL_ACTIVATION_TYPE;
typedef struct _tagSL_ACTIVATION_INFO_HEADER {
DWORD cbSize;
SL_ACTIVATION_TYPE type;
} SL_ACTIVATION_INFO_HEADER;
*/
typedef HRESULT WINAPI (*LPFN_SLActivateProduct)(HSLC, const SLID*, UINT, const PVOID, const SL_ACTIVATION_INFO_HEADER*, PCWSTR, WORD);
int main()
{
LPFN_SLActivateProduct lpSLActivateProduct = (LPFN_SLActivateProduct) GetProcAddress(GetModuleHandle(TEXT("slc.dll")), "SLActivateProduct");
if (!lpSLActivateProduct)
{
printf("SLActivateProduct - The product cannot be activated on this system\n");
return 0;
}
HSLC hslc;
HRESULT hr = SLOpen(&hslc);
if (FAILED(hr))
{
printf("SLOpen - unknown return code 0x%08X\n", hr);
return 0;
}
// try to activate windows
hr = lpSLActivateProduct(hslc, &WINDOWS_SLID, 0, NULL, NULL, NULL, 0);
switch(hr)
{
case E_INVALIDARG:
printf("SLActivateProduct - one or more arguments are not valid\n");
break;
case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case SL_E_PKEY_NOT_INSTALLED:
printf("SLActivateProduct - The product key is not available\n");
break;
case SL_E_PRODUCT_SKU_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case S_OK:
printf("SLActivateProduct - returned S_OK\n");
break;
default:
printf("SLActivateProduct - unknown return code 0x%08X\n", hr);
break;
}
hr = SLClose(hslc);
return 0;
}
更新:毕竟,在Windows 7上可以看到SLActivateProduct()
IS 。就像MSDN所说的那样,它只是位于slcext.dll
而不是slc.dll
。您可以相应地调整GetProcAddress()
电话:
LPFN_SLActivateProduct lpSLActivateProduct = (LPFN_SLActivateProduct) GetProcAddress(GetModuleHandle(TEXT("slc.dll")), "SLActivateProduct");
if (!lpSLActivateProduct)
{
// TODO: if SLCEXT.DLL is not already loaded, use LoadLibrary() instead of GetModuleHandle()...
lpSLActivateProduct = (LPFN_SLActivateProduct) GetProcAddress(GetModuleHandle(TEXT("slcext.dll")), "SLActivateProduct");
}
if (!lpSLActivateProduct)
{
printf("SLActivateProduct - The product cannot be activated on this system\n");
return 0;
}
更新:如果稍后将更新到slc.lib
不再缺少对SLActivateProduct()
的引用的开发环境,则可以删除显式调用到GetProcAddress()
,而是使用链接器的delay loaded DLLs feature。这允许您编写代码 - 如果您是静态链接,但随后链接器将注入特殊代码,在运行时第一次调用DLL函数时将为您调用GetProcAddress()
。这将允许您在“静态”调用函数之前检查操作系统版本,允许您的应用程序仍然在较旧的Windows版本上运行,但仅在Windows 7 +上执行激活。
#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <sliddefs.h>
#include <stdio.h>
// lib to use
#pragma comment(lib, "slc.lib")
// if your version of Slpublic.h does not define these then uncomment this...
/*
typedef enum _tagSL_ACTIVATION_TYPE {
SL_ACTIVATION_TYPE_DEFAULT = 0,
SL_ACTIVATION_TYPE_ACTIVE_DIRECTORY = 1
} SL_ACTIVATION_TYPE;
typedef struct _tagSL_ACTIVATION_INFO_HEADER {
DWORD cbSize;
SL_ACTIVATION_TYPE type;
} SL_ACTIVATION_INFO_HEADER;
*/
int main()
{
OSVERSIONINFO osi = {0};
osi.dwOSVersionInfoSize = sizeof(osi).
GetVersionEx(&osi);
if ((osi.dwMajorVersion < 6) || ((osi.dwMajorVersion == 6) && (dwMinorVersion < 1)))
{
printf("SLActivateProduct - The product cannot be activated on this system\n");
return 0;
}
// alternatively:
/*
#include <VersionHelpers.h>
if (!IsWindows7OrGreater())
{
printf("SLActivateProduct - The product cannot be activated on this system\n");
return 0;
}
*/
HSLC hslc;
HRESULT hr = SLOpen(&hslc);
if (FAILED(hr))
{
printf("SLOpen - unknown return code 0x%08X\n", hr);
return 0;
}
// try to activate windows
hr = SLActivateProduct(hslc, &WINDOWS_SLID, 0, NULL, NULL, NULL, 0);
switch(hr)
{
case E_INVALIDARG:
printf("SLActivateProduct - one or more arguments are not valid\n");
break;
case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case SL_E_PKEY_NOT_INSTALLED:
printf("SLActivateProduct - The product key is not available\n");
break;
case SL_E_PRODUCT_SKU_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case S_OK:
printf("SLActivateProduct - returned S_OK\n");
break;
default:
printf("SLActivateProduct - unknown return code 0x%08X\n", hr);
break;
}
hr = SLClose(hslc);
return 0;
}
但是,要解决slc.dll
vs slcext.dll
问题,您可以使用delay-load failure hook检测SLActivateProduct()
中何时找不到slc.dll
,然后从slcext.dll
加载它。
实际上,这是首选方案,因为它还提供了另一个机会 - 它允许您完全删除操作系统版本检查!如果在任一DLL中找不到SLActivateProduct()
,则可以返回指向自定义用户定义函数的指针。当代码调用SLActivateProduct()
时,如果它调用该函数,它只能返回E_NOTIMPL
,main()
可以在其switch
语句中处理:
#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <sliddefs.h>
#include <stdio.h>
#include <delayimp.h>
// lib to use
#pragma comment(lib, "slc.lib")
// if your version of Slpublic.h does not define these then uncomment this...
/*
typedef enum _tagSL_ACTIVATION_TYPE {
SL_ACTIVATION_TYPE_DEFAULT = 0,
SL_ACTIVATION_TYPE_ACTIVE_DIRECTORY = 1
} SL_ACTIVATION_TYPE;
typedef struct _tagSL_ACTIVATION_INFO_HEADER {
DWORD cbSize;
SL_ACTIVATION_TYPE type;
} SL_ACTIVATION_INFO_HEADER;
*/
HRESULT WINAPI Dummy_SLActivateProduct(HSLC, const SLID*, UINT, const PVOID, const SL_ACTIVATION_INFO_HEADER*, PCWSTR, WORD)
{
return E_NOTIMPL;
}
HMODULE hSlcExtDll = NULL;
FARPROC WINAPI MyDliFailureHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
if ((dliNotify == dliFailGetProc) && (pdli->dlp.fImportByName) && (lstrcmpA(pdli->dlp.szProcName, "SLActivateProduct") == 0))
{
hSlcExtDll = LoadLibrary("slcext.dll");
FARPROC fn = GetProcAddress(hSlcExtDll, "SLActivateProduct");
if (!fn) fn = &Dummy_SLActivateProduct;
return fn;
}
return NULL;
}
int main()
{
__pfnDliFailureHook2 = &MyDliFailureHook;
HSLC hslc;
HRESULT hr = SLOpen(&hslc);
if (FAILED(hr))
{
printf("SLOpen - unknown return code 0x%08X\n", hr);
return 0;
}
// try to activate windows
hr = SLActivateProduct(hslc, &WINDOWS_SLID, 0, NULL, NULL, NULL, 0);
switch(hr)
{
case E_NOTIMPL:
printf("SLActivateProduct - The product cannot be activated on this system\n");
break;
case E_INVALIDARG:
printf("SLActivateProduct - one or more arguments are not valid\n");
break;
case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case SL_E_PKEY_NOT_INSTALLED:
printf("SLActivateProduct - The product key is not available\n");
break;
case SL_E_PRODUCT_SKU_NOT_INSTALLED:
printf("SLActivateProduct - The license is not installed\n");
break;
case S_OK:
printf("SLActivateProduct - returned S_OK\n");
break;
default:
printf("SLActivateProduct - unknown return code 0x%08X\n", hr);
break;
}
hr = SLClose(hslc);
return 0;
}