C++ 无法使用SQL VDI(虚拟设备接口)创建条带化备份

C++ 无法使用SQL VDI(虚拟设备接口)创建条带化备份,c++,sql-server,com,database-backups,C++,Sql Server,Com,Database Backups,这是一个难以置信的远射,但现在开始。我们正在使用SQLVDIAPI(虚拟设备接口)制作一个数据库备份实用程序。单一备份的实施没有任何问题。但是,当我们开始实施条带化备份(使用虚拟_设备)时,我们遇到了iclientvirtualdevicet2::OpenDevice方法的问题。 我们的虚拟设备集无法打开所有设备。只返回第一个设备,在第二个设备上我们得到VD\u E\u协议错误。如有任何建议,将不胜感激 我们的C++代码.< /P> public: Void ExecuteCommandEx(S

这是一个难以置信的远射,但现在开始。我们正在使用SQLVDIAPI(虚拟设备接口)制作一个数据库备份实用程序。单一备份的实施没有任何问题。但是,当我们开始实施条带化备份(使用虚拟_设备)时,我们遇到了
iclientvirtualdevicet2::OpenDevice
方法的问题。 我们的虚拟设备集无法打开所有设备。只返回第一个设备,在第二个设备上我们得到
VD\u E\u协议
错误。如有任何建议,将不胜感激

我们的C++代码.< /P>

public: Void ExecuteCommandEx(System::String^ command, array<Stream^>^ commandStreamListIn)
{
    try
    {
        //Initialize COM
        HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
        if (FAILED(hr))
        {
            throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "CoInitializeEx Failed HRESULT: {0}", hr));
        }
        //Get an interface to the virtual device set
        IClientVirtualDeviceSet2* vds = NULL;
        hr = CoCreateInstance(CLSID_MSSQL_ClientVirtualDeviceSet, NULL, CLSCTX_INPROC_SERVER, IID_IClientVirtualDeviceSet2, (void**)&vds);
        if (FAILED(hr))
        {
            throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "Unable to get an interface to the virtual device set.  Please check to make sure sqlvdi.dll is registered. HRESULT: {0}", hr));
        }
        //Configure the device configuration
        VDConfig config = { 0 };
        config.deviceCount = commandStreamListIn->Length; //The number of virtual devices to create
        //Create a name for the device using a GUID
        String^ DeviceName = Guid::NewGuid().ToString()->ToUpper(gcnew CultureInfo("en-US"));
        WCHAR wVdsName[37] = { 0 };
        Marshal::Copy(DeviceName->ToCharArray(), 0, (IntPtr)wVdsName, DeviceName->Length);
        //Create the virtual device set
        hr = vds->CreateEx(NULL, wVdsName, &config);
        if (FAILED(hr))
        {
            throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "Unable to create and configure the virtual device set. HRESULT: {0}", hr));
        }
        //Format the command
        List<String^>^ vdNames = gcnew List<String^>();
        vdNames->Add(DeviceName);
        for (int i = 0; i < commandStreamListIn->Length-1; i++)
        {
            String^ streamName = Guid::NewGuid().ToString()->ToUpper(gcnew CultureInfo("en-US"));
            vdNames->Add(streamName);
        }
        command = String::Format(gcnew CultureInfo("en-US"), command, vdNames->ToArray());
        //Create and execute a new thread to execute the command
        Thread^ OdbcThread = gcnew Thread(gcnew ParameterizedThreadStart(this, &VdiDotNetEx::VdiEngineEx::ThreadFunc));
        OdbcThread->Start(command);
        //Configure the virtual device set
        hr = vds->GetConfiguration(INFINITE, &config);
        if (hr != NOERROR)
        {
            throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "GetConfiguration Failed.  HRESULT: {0}", hr));
        }
        if (FAILED(hr))
        {
            switch (hr)
            {
                case VD_E_ABORT:
                    throw gcnew ApplicationException("GetConfiguration was aborted.");
                    break;
                case VD_E_TIMEOUT:
                    throw gcnew ApplicationException("GetConfiguration timed out.");
                    break;
                default:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "Un unknown exception was thrown during GetConfiguration.  HRESULT: {0}", hr));
                    break;
            };
        }
        int count = 0;
        array<IClientVirtualDevice*>^ vDevices= gcnew array<IClientVirtualDevice*>(commandStreamListIn->Length);

        //Open all devices on the device set
        //VD_E_OPEN may be returned without problem. The client may call OpenDevice by means of a loop until this code is returned.
        //If more than one device is configured(for example, n devices),
        //the virtual device set will return n unique device interfaces.
        //The first device has the same name as the virtual device set.
        //Other devices are named as specified with the VIRTUAL_DEVICE clauses of the BACKUP / RESTORE statement.

        while (hr!= VD_E_OPEN)
        {
            IClientVirtualDevice* vd = NULL;
            hr = vds->OpenDevice(wVdsName, &vd);
            switch(hr)
            {
                case VD_E_OPEN:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_OPEN.  HRESULT: {0}", hr));
                    break;
                case VD_E_BUSY:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_BUSY.  HRESULT: {0}", hr));
                    break;
                case VD_E_CLOSE:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_CLOSE.  HRESULT: {0}", hr));
                    break;
                case VD_E_UNEXPECTED:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_UNEXPECTED.  HRESULT: {0}", hr));
                    break;
                case VD_E_INVALID:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_INVALID.  HRESULT: {0}", hr));
                    break;
                case VD_E_NOTOPEN:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_NOTOPEN.  HRESULT: {0}", hr));
                    break;
                case VD_E_PROTOCOL:
                    throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_PROTOCOL.  HRESULT: {0}", hr));
                    break;
            }
            if (FAILED(hr))
            {
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed.  HRESULT: {0}", hr));
            }
            vDevices[count] = vd;

            count++;
        }
        for (int i = 0; i < count; i++)
        {
            ExecuteDataTransfer(vDevices[i], commandStreamListIn[i]);
        }

        //Wait for the thread that issued the backup / restore command to SQL Server to complete.
        OdbcThread->Join();
    }
    catch (Exception ^ex)
    {
        Debug::WriteLine("VDI: Exception=" + ex->Message->ToString());
        Debug::WriteLine("VDI: Trace=" + ex->StackTrace);
        Console::WriteLine(ex->Message);
        LogException(ex);
        throw gcnew ApplicationException(ex->Message);
    }
}

OpenDevice未根据SQLVDI文档工作。例如,不要期望VD_E_打开,只要0就可以了。另外,不仅要将虚拟设备集名称传递给此方法,还要从命令中传递每个虚拟设备的GUID。看看这个调整后的代码

for(int i = 0; i < vdNames->Count; i++)
    {
        IClientVirtualDevice* vd = NULL;
        WCHAR wDevName[37] = { 0 };

        String^ vdName = vdNames[i];
        Marshal::Copy(vdName->ToCharArray(), 0, (IntPtr)wDevName, vdName->Length);

        hr = vds->OpenDevice(wDevName, &vd);
        switch(hr)
        {
            case VD_E_BUSY:
                DBGPRINTW(L"VDI: Exception 15\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_BUSY.  HRESULT: {0}", hr));
            break;
            case VD_E_CLOSE:
                DBGPRINTW(L"VDI: Exception 14\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_CLOSE.  HRESULT: {0}", hr));
            break;
            case VD_E_UNEXPECTED:
                DBGPRINTW(L"VDI: Exception 11\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_UNEXPECTED.  HRESULT: {0}", hr));
            break;
            case VD_E_INVALID:
                DBGPRINTW(L"VDI: Exception 06\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_INVALID.  HRESULT: {0}", hr));
            break;
            case VD_E_NOTOPEN:
                DBGPRINTW(L"VDI: Exception 02\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_NOTOPEN.  HRESULT: {0}", hr));
            break;
            case VD_E_PROTOCOL:
                DBGPRINTW(L"VDI: Exception 12\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_PROTOCOL.  HRESULT: {0}", hr));
                break;

        }
        if (FAILED(hr))
        {
            DBGPRINTW(L"VDI: Exception 08\n");
            throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed.  HRESULT: {0}", hr));
        }

        vDevices[i] = vd;
        count++;
    }
for(int i=0;iCount;i++)
{
IClientVirtualDevice*vd=NULL;
WCHAR wDevName[37]={0};
字符串^vdName=vdNames[i];
封送:复制(vdName->ToCharArray(),0,(IntPtr)wDevName,vdName->Length);
hr=vds->OpenDevice(wDevName,&vd);
开关(hr)
{
案例VD_E_忙碌:
DBGPRINTW(L“VDI:异常15\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice Failed.VD_E_BUSY.HRESULT:{0}”,hr));
打破
案例VDU E_关闭:
DBGPRINTW(L“VDI:异常14\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice Failed.VD_E_CLOSE.HRESULT:{0}”,hr));
打破
意外情况:
DBGPRINTW(L“VDI:异常11\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice失败。VD_E_意外。HRESULT:{0}”,hr));
打破
案例VD_E_无效:
DBGPRINTW(L“VDI:异常06\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice失败。VD_E_无效。HRESULT:{0}”,hr));
打破
案例VD_E_NOTOPEN:
DBGPRINTW(L“VDI:异常02\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice Failed.VD_E_NOTOPEN.HRESULT:{0}”,hr));
打破
案例VDU E_协议:
DBGPRINTW(L“VDI:异常12\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice Failed.VD_E_PROTOCOL.HRESULT:{0}”,hr));
打破
}
如果(失败(小时))
{
DBGPRINTW(L“VDI:异常08\n”);
抛出gcnew ApplicationException(字符串::格式(gcnew CultureInfo(“en-US”),“OpenDevice失败。HRESULT:{0}”,hr));
}
vDevices[i]=vd;
计数++;
}

您也可以在dba.stackexchange.com上询问。作为一名开发人员,我设计数据库并编写大量SQL,但对备份没有专门的知识。
for(int i = 0; i < vdNames->Count; i++)
    {
        IClientVirtualDevice* vd = NULL;
        WCHAR wDevName[37] = { 0 };

        String^ vdName = vdNames[i];
        Marshal::Copy(vdName->ToCharArray(), 0, (IntPtr)wDevName, vdName->Length);

        hr = vds->OpenDevice(wDevName, &vd);
        switch(hr)
        {
            case VD_E_BUSY:
                DBGPRINTW(L"VDI: Exception 15\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_BUSY.  HRESULT: {0}", hr));
            break;
            case VD_E_CLOSE:
                DBGPRINTW(L"VDI: Exception 14\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_CLOSE.  HRESULT: {0}", hr));
            break;
            case VD_E_UNEXPECTED:
                DBGPRINTW(L"VDI: Exception 11\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_UNEXPECTED.  HRESULT: {0}", hr));
            break;
            case VD_E_INVALID:
                DBGPRINTW(L"VDI: Exception 06\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_INVALID.  HRESULT: {0}", hr));
            break;
            case VD_E_NOTOPEN:
                DBGPRINTW(L"VDI: Exception 02\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_NOTOPEN.  HRESULT: {0}", hr));
            break;
            case VD_E_PROTOCOL:
                DBGPRINTW(L"VDI: Exception 12\n");
                throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed. VD_E_PROTOCOL.  HRESULT: {0}", hr));
                break;

        }
        if (FAILED(hr))
        {
            DBGPRINTW(L"VDI: Exception 08\n");
            throw gcnew ApplicationException(String::Format(gcnew CultureInfo("en-US"), "OpenDevice Failed.  HRESULT: {0}", hr));
        }

        vDevices[i] = vd;
        count++;
    }