3

我使用的是旧版本的 SQL Server (2000)。我不希望我的用户有权运行 master.dbo.xp_cmdshell。我正在尝试创建一个自定义 DLL,我可以使用它来创建我自己的扩展存储过程,我授予用户运行权限 - 一个硬编码以执行用户需要能够按需运行的特定批处理文件。

我正在使用 Visual Studio 2010 创建 DLL。这是我的头文件stdafx.h:

#define WIN32_LEAN_AND_MEAN 

#include <windows.h>
#include <iostream>

#ifndef INDLL_H
    #define INDLL_H

    #ifdef EXPORTING_DLL
        extern __declspec(dllexport) void HelloWorld() ;
    #else
        extern __declspec(dllimport) void HelloWorld() ;
    #endif
#endif

这是我的主文件 dllmain.cpp:

#include "stdafx.h"
#define EXPORTING_DLL

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                   LPVOID lpReserved)
{ return TRUE; }

void HelloWorld() {
    system("f:\\bin\\batchfilename.bat");
}

当我尝试调试此项目时,我看到构建成功,但我收到错误“无法启动程序:<path to compiled dll>。” 你认为这个 DLL 会工作吗?如果可以,我该如何测试它以查看它是否工作?

4

2 回答 2

3

好的,经过几个小时的谷歌搜索,我成功编译了一个 DLL 以添加为 SQL Server 2000 扩展存储过程。我将在这里分享它,因为它只是我从谷歌搜索中收集的东西的汇编。(我使用了 Visual Studio 2010)。我不会发布所有内容 - 我首先在 Visual Studio 中创建一个新项目并选择 Win32 Console Application,然后选择 Next,然后选择 DLL。它会为您创建一些头文件和其他文件。其中一些我认为没有必要。还有一些你必须手动添加到项目中的头文件。但这是我的主要 .cpp 代码:

#include "stdafx.h"         
#include "srv.h"   //Must get from C:\Program Files (x86)\Microsoft SQL Server\80\Tools\DevTools\Include            
#include "shellapi.h"  //need for ShellExecute          
#include "string"   //needed for std:string         
#include <sys/stat.h>  //need for stat in fileExists function below         

#define DLL_FUNC extern "C" __declspec (dllexport)          

__declspec(dllexport) ULONG __GetXpVersion() {          
   return ODS_VERSION;          
}           

bool fileExists(const std::string& filename) {          
    struct stat buf;            
    if (stat(filename.c_str(), &buf) != -1)         
    { return true; }            
    return false;           
}           

DLL_FUNC int __stdcall RunPP() {            
    if (fileExists("C:\\FileOnServer\\execute.bat")) {      
        ShellExecute(NULL,TEXT("open"), TEXT("C:\\FileOnServer\\execute.bat"), NULL, NULL,SW_SHOWNORMAL);       
        return 0;   
    } else {        
        MessageBox(HWND_DESKTOP, TEXT("File not found."), TEXT("Message"), MB_OK);  
        return 1;   
    }       
}           

我了解到您可以rundll32 yourdllname.dll,functionname在命令行中使用 rundll32({逗号后无空格})测试此 DLL,但前提是您在项目中包含 .def 文件。我的def文件是

LIBRARY
EXPORTS
RunPP

此外,正如文档所述,我尝试在 Project > Properties... > Linker > Input > Additional Dependencies 中添加对 Opends60.lib 的引用,但看起来它在某些时候被删除了。

对于像我这样的新手,我必须在项目的属性页面中学习很多东西,比如将 C/C++ > 代码生成 > 运行时库切换到 /MD。还学习如何在 Release 模式下编译,在哪里找到生成的 .dll 文件等。

然后,将编译后的 DLL 移动到我的 SQL Server 机器 (Win2003R2) 时,我必须安装 VC++ 2010 Redistributable 才能运行。然后我将 DLL 复制到我机器上的 C:\Program Files\Microsoft SQL Server\MSSQL\Binn (与 xp_cmdShell 扩展存储过程的 DLL 所在的位置相同),然后根据文档运行 sp_addextendedproc 以将其注册为可用的扩展存储主数据库中的过程。然后授予用户执行它的权限等。

我知道这一切都是一项古老的技术。我应该升级我的 SQL Server 版本。但也许这会帮助别人。

于 2012-10-05T22:24:45.220 回答
0

你有两个选择:

  1. 而不是“运行” DDL,而是附加到正在运行的进程:sqlservr.exe。设置断点,然后加载 XP。调试器断点将触发,您可以单步执行代码。

  2. 将项目启动选项更改为启动外部程序并选择 sqlservr.exe 作为外部程序。

这两个选项都要求您知道自己在做什么,尤其是第二个选项(例如,确保服务已停止,在启动​​参数中指定实例名称并有权访问 SQL 数据目录)。

显然,更好的选择是升级到 SQL Server 2005(至少)并改用 SQLCLR。

于 2012-10-05T20:58:43.897 回答