我编写了演示应用,试图学习如何使用ADO
流。除了一个特殊情况外,一切正常。首先让我提供相关信息:
我正在使用WinAPI
创建GUI,并在按下按钮时加载(并将其保存在磁盘上)/插入BLOB。按钮位于对话框中。
当我按下按钮将BLOB插入数据库时,我可以看到它被插入(我保持MS Access打开)。如果我尝试从数据库加载任何现有的BLOB,则不会发生任何错误信号。
但是,如果我执行insert,然后关闭并重新打开对话框,按下按钮以加载BLOB并将其保存到磁盘中效果很好。
我在x64双核CPU笔记本电脑上使用Visual Studio 2013在Windows 8.1上工作(这可能很重要)。 我已经在C:\分区中测试了我的应用程序操作系统,只是提到它是相关的。
编辑:
我在D分区上尝试了我的应用程序,但它确实有效。这意味着问题出在权限的某个地方。你能帮助我吗,因为我不知道如何开始解决这个问题?
END OF EDIT
为了进一步帮助您,请仔细按照说明创建非常简单的代码示例来重现问题:
1。)在Visual Studio中创建default Win32 project
。
2。)在stdafx.h
#include <windows.h>
下面添加以下内容:
#include <comutil.h>
#include <stdio.h>
#include <ole2.h>
#include <string>
#include <shlwapi.h>
#pragma comment( lib, "comsuppw.lib")
#pragma comment( lib, "shlwapi.lib")
3。)在.cpp
指令下面的主#include
文件中添加以下内容:
#import <C:\\Program Files\\Common Files\\System\\ado\\msado15.dll> \
rename( "EOF", "AdoNSEOF" )
4.。)在对话框程序About
上面添加以下函数:
BOOL OpenFile(HWND hDlg, LPWSTR szFileName, LPWSTR szFilter)
{
// prepare OPENFILE dialog
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDlg;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFileName;
ofn.lpstrFile[0] = L'\0';
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST |
OFN_DONTADDTORECENT | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = L".pdf";
if (GetOpenFileName(&ofn))
return TRUE;
return FALSE;
}
5.用这个替换About
对话框程序:
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
// connection string
static wchar_t bstrConnect[MAX_PATH];
switch (message)
{
case WM_INITDIALOG:
{
// create connection string by choosing database
wchar_t szFile[MAX_PATH];
OpenFile(hDlg, szFile, L".accdb\0");
swprintf_s(bstrConnect, MAX_PATH,
L"Provider=Microsoft.ACE.OLEDB.12.0; Data Source = %s;", szFile);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON1) // save BLOB to database
{
wchar_t szFileName[MAX_PATH] = L"";
if (OpenFile(hDlg, szFileName, L"All files\0*.*"))
{
try
{
HRESULT hr = CoInitialize(NULL);
ADODB::_ConnectionPtr pConn(L"ADODB.Connection");
ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");
hr = pConn->Open(bstrConnect,
L"", L"", ADODB::adConnectUnspecified);
// create new recordset
pRS->Open( L"test", _variant_t((IDispatch*)pConn, true),
ADODB::adOpenKeyset,
ADODB::adLockOptimistic,
ADODB::adCmdTable);
// create stream object
ADODB::_StreamPtr pStream(L"ADODB.Stream");
// set stream type
pStream->Type = ADODB::adTypeBinary;
// missing parameter for Open
_variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
// open stream
pStream->Open(varOptional,
ADODB::adModeUnknown,
ADODB::adOpenStreamUnspecified,
_bstr_t(L""), _bstr_t(L""));
// open selected file
hr = pStream->LoadFromFile(szFileName);
// error checking
if (FAILED(hr))
throw _com_error(hr);
// add new blank record
pRS->AddNew();
// position stream to beginning
pStream->Position = 0;
// insert data to recordset
PathStripPath(szFileName); // leave only filename
pRS->Fields->GetItem(L"tip")->Value = szFileName;
pRS->Fields->GetItem(L"field")->Value =
pStream->Read(ADODB::adReadAll);
// insert data
pRS->Update();
//cleanup
pRS->Close();
pConn->Close();
pStream->Close();
CoUninitialize();
MessageBeep(0);
}
catch (_com_error e)
{
MessageBox(hDlg, (LPWSTR)e.Description(), L"", 0);
}
}
}
if (LOWORD(wParam) == IDC_BUTTON3) // load BLOB and save it into disk
{
try
{
// napravi upit
HRESULT hr = CoInitialize(NULL);
ADODB::_ConnectionPtr pConn(L"ADODB.Connection");
ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");
hr = pConn->Open(bstrConnect, L"", L"", ADODB::adConnectUnspecified);
// create stream object
ADODB::_StreamPtr pStream(L"ADODB.Stream");
// set stream type
pStream->Type = ADODB::adTypeBinary;
// missing parameter for Open
_variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
// open stream
pStream->Open(varOptional,
ADODB::adModeUnknown,
ADODB::adOpenStreamUnspecified,
_bstr_t(L""), _bstr_t(L""));
// primary key is taken from edit control
wchar_t query[200] = L"";
swprintf_s(query, 200, L"select tip, field from test where ID = %d;",
(int)GetDlgItemInt(hDlg, IDC_EDIT1, FALSE, FALSE));
pRS->Open(query, _variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified, ADODB::adLockPessimistic,
ADODB::adCmdText);
if (NULL == pRS)
MessageBox(hDlg, L"Empty recordset!", L"", 0);
hr = pStream->Write(pRS->Fields->GetItem(L"field")->Value);
if (FAILED(hr))
MessageBox(hDlg, L"stream write failed", L"", 0);
// save to file
// store this file on disk
// int he same place our app is running
wchar_t szFileName[MAX_PATH] = L"";
swprintf_s(szFileName, MAX_PATH, L".\\%s",
pRS->Fields->GetItem(L"tip")->Value.bstrVal);
hr = pStream->SaveToFile(szFileName, ADODB::adSaveCreateOverWrite);
if (FAILED(hr))
MessageBox(hDlg, L"save to file failed", L"", 0);
//cleanup
pRS->Close();
pConn->Close();
pStream->Close();
CoUninitialize();
MessageBeep(0);
}
catch (_com_error e)
{
MessageBox(hDlg, (LPWSTR)e.Description(), L"", 0);
}
}
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
7。)About
编辑器中的返工rc
对话框,如下所示:
auto buddy
,right align, and
设置好友整数样式集8。)使用以下字段创建MS Access数据库:
autonumber
,primary key
OLE Object
text
此字段存储文件名(file.extension) 如何使用此应用程序:
运行应用程序时,打开About
菜单项,以便弹出对话框。选择我们创建的数据库
单击左侧按钮(从之前提交的图像中的蓝色圆圈)。打开文件对话框弹出,您可以选择任何文件(我尝试使用.pdf
,.exe
,.zip
和jpeg
)。文件应插入数据库。
要阅读BLOB并将其保存在应用程序运行的相同位置,请键入要检索的记录数,然后按右键(从之前提交的图片中的红色圆圈)。应该加载BLOB,然后将其保存在应用程序所在的相同位置。
这不是生产代码,请注意这一点。这只是解释问题的最小,最简单的代码示例。
同样,如果你插入BLOB然后尝试加载它,没有任何反应,但代码运行没有错误。
如果您插入BLOB,然后关闭对话框,再次打开对话框,然后尝试从数据库加载BLOB一切正常。
如何重写我的代码,以便我可以插入,然后加载BLOB而不诉诸&#34;解决方案#2&#34;如前所述。
编辑:
我在D分区上尝试了我的应用程序,但它确实有效。这意味着问题出在权限的某个地方。你能帮助我吗,因为我不知道如何开始解决这个问题?
END OF EDIT
谢谢。
答案 0 :(得分:2)
通常情况下,当我自己解决问题并且没有答案时,我只是删除了问题。但是,发布的代码对于后代来说可能是一个很好的工作示例。
问题在于我构建文件路径。在重写我的代码后,一切正常。这是完整的对话程序:
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
// connection string
static wchar_t bstrConnect[MAX_PATH];
switch (message)
{
case WM_INITDIALOG:
{
wchar_t szFile[MAX_PATH];
OpenFile(hDlg, szFile, L".accdb\0");
swprintf_s(bstrConnect, MAX_PATH,
L"Provider=Microsoft.ACE.OLEDB.12.0; Data Source = %s;", szFile);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON1:
{
wchar_t szFileName[MAX_PATH] = L"";
if (OpenFile(hDlg, szFileName, L"All files\0*.*"))
{
try
{
// disable write button, just in case, until we finish inserting
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON3), FALSE);
HRESULT hr = CoInitialize(NULL);
ADODB::_ConnectionPtr pConn(L"ADODB.Connection");
ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");
hr = pConn->Open(bstrConnect, L"", L"",
ADODB::adConnectUnspecified);
// create new recordset
pRS->Open(L"test", _variant_t((IDispatch*)pConn, true),
ADODB::adOpenKeyset, ADODB::adLockOptimistic,
ADODB::adCmdTable);
// create stream object
ADODB::_StreamPtr pStream(L"ADODB.Stream");
// set stream type
pStream->Type = ADODB::adTypeBinary;
// missing parameter
_variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
// open stream
pStream->Open(varOptional, ADODB::adModeUnknown,
ADODB::adOpenStreamUnspecified, _bstr_t(L""), _bstr_t(L""));
// open selected file
hr = pStream->LoadFromFile(szFileName);
if(FAILED(hr))
throw _com_error(hr);
// add new blank record
pRS->AddNew();
// position stream
pStream->Position = 0;
// insert data to recordset
PathStripPath(szFileName); // leave only filename
pRS->Fields->GetItem(L"tip")->Value = szFileName; // store filename
pRS->Fields->GetItem(L"field")->Value =
pStream->Read(ADODB::adReadAll); // store BLOB
// insert data
pRS->Update();
//cleanup
pRS->Close();
pConn->Close();
pStream->Close();
CoUninitialize();
// now is safe to read BLOB from database so enable load button
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON3), TRUE);
// make a sound just so we know we made it! :)
MessageBeep(0);
}
catch (_com_error e)
{
MessageBox(hDlg, (LPWSTR)e.Description(), L"", 0);
}
}
}
break;
case IDC_BUTTON3:
{
try
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
throw _com_error(hr);
ADODB::_ConnectionPtr pConn(L"ADODB.Connection");
ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");
hr = pConn->Open(bstrConnect, L"", L"", ADODB::adConnectUnspecified);
if (FAILED(hr))
{
MessageBox(hDlg, L"connection error", L"", 0);
throw _com_error(hr);
}
// create stream object
ADODB::_StreamPtr pStream(L"ADODB.Stream");
// set stream type
pStream->Type = ADODB::adTypeBinary;
// missing parameter
_variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
hr = pStream->Open(varOptional, ADODB::adModeUnknown,
ADODB::adOpenStreamUnspecified, _bstr_t(L""), _bstr_t(L""));
if (FAILED(hr))
{
MessageBox(hDlg, L"connection error", L"", 0);
throw _com_error(hr);
}
wchar_t query[200] = L"";
BOOL ok = true; // needed for error checking ( GetDlgInt -> see the docs )
swprintf_s(query, 200, L"select tip, field from test where ID = %d;",
(int)GetDlgItemInt(hDlg, IDC_EDIT1, &ok, FALSE));
if (!ok)
MessageBox(hDlg, L"dlgitemint failed", L"", 0);
hr = pRS->Open(query, _variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified, ADODB::adLockPessimistic,
ADODB::adCmdText);
if (FAILED(hr))
{
MessageBox(hDlg, L"connection error", L"", 0);
throw _com_error(hr);
}
if (NULL == pRS)
{
MessageBox(hDlg, L"NULL pRS!", L"", 0);
throw _com_error(hr);
}
if (pRS->BOF && pRS->AdoNSEOF)
MessageBox(hDlg, L"empty rs", L"", 0);
hr = pStream->Write(pRS->Fields->GetItem(L"field")->Value);
if (!pStream->GetSize())
MessageBox(hDlg, L"stream write failed", L"", 0);
if (FAILED(hr))
{
MessageBox(hDlg, L"stream write failed", L"", 0);
throw _com_error(hr);
}
// save to file
wchar_t szFileName[MAX_PATH] = L"";
// this returns directory where our exe is running
GetModuleFileName(NULL, szFileName, MAX_PATH);
// now we remove name and extension of the exe file
PathRemoveFileSpec(szFileName);
// add backslash at the end
PathAddBackslash(szFileName);
// now we "glue" the name of our BLOB ( we stored it into DB )
wcscat_s(szFileName, MAX_PATH,
pRS->Fields->GetItem(L"tip")->Value.bstrVal);
if (!wcslen(szFileName))
MessageBox(hDlg, L"load field name failed", L"", 0);
hr = pStream->SaveToFile(szFileName, ADODB::adSaveCreateOverWrite);
if (FAILED(hr))
{
MessageBox(hDlg, L"save to file failed", L"", 0);
throw _com_error(hr);
}
//cleanup
pRS->Close();
pConn->Close();
pStream->Close();
CoUninitialize();
// beep so we know all went well
MessageBeep(0);
}
catch (_com_error e)
{
MessageBox(hDlg, (LPWSTR)e.Description(), L"", 0);
}
}
break;
case IDOK:
case IDCANCEL:
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
default:
break;
}
}
return (INT_PTR)FALSE;
}
这只是一个测试代码,但仍然是我工作的重要部分(插入或加载+保存BLOB)。希望它对未来的读者有用。
如果其他成员有改进读取/写入BLOB的代码部分的建议,请发表评论。建设性的批评总是受欢迎的。
我重写了代码,几乎可以存储任何文件。我已成功测试了GIF,PDF,DOCX,XLSX,JPEG,BMP,EXE和TXT。我也在USB上运行我的应用程序,它也运行良好。