RegQueryValueExで2バイト文字の取得方法について

このQ&Aのポイント
  • RegQueryValueExを使ってレジストリキーから値を取得する際、2バイト文字(日本語のフォルダ名など)が含まれると、データが切れてしまってしまいます。
  • 正しく取得するためにはどのように実装すればよいでしょうか?
  • 2バイト文字がない場合は正常に取得できることが確認されています。
回答を見る
  • ベストアンサー

RegQueryValueExでの2バイト文字

RegQueryValueExを使ってレジストリキーから値をとってきたいのですが、そのキー(REG_SZ)にはファイルパスが記載されており、そのキーを取得するときに2バイト文字(日本語のフォルダ名)があるとそこでデータが切れてしまって取得してしまいます。 c:\test\テスト\aaa.dll とあるとテスト直前のc:\test\しか取得できません。以下の例ではEntryのキーに上記dllパスが記載されてます。 char data[256]; DWORD dwSize; DWORD dwSize; RegQueryValueEx(hKey,(LPCTSTR)Entry,NULL,&dwType,NULL,&dwSize); RegQueryValueEx(hKey,(LPCTSTR)Entry,NULL,&dwType,(LPBYTE)data,&dwSize); 2バイト文字がないと正しく取得できます。 どのように実装すればよいでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

とりあえず、途中で切れてしまう場合の RegQueryValueEx の戻り値と、RegQueryValueEx 実行後の dwSize の値はどうなっていますか? ところで、掲載されているコードは実際のコードではありませんよね?( 「DWORD dwSize;」 が二つある。) 省略したところに原因がある場合もあるので、実際のコードをコピー&ペーストで貼り付けた方が良いと思います。 文字が途中で切れる問題とは関係ないのですが、 RegQueryValueEx(hKey,(LPCTSTR)Entry,NULL,&dwType,NULL,&dwSize); で取得した dwSize が、data のサイズ ( 256 ) 以下かどうかのチェックって、されてますか? dwSize が data のサイズより大きくなることはあり得ないということで dwSize のチェックを行わないのであれば、 RegQueryValueEx(hKey,(LPCTSTR)Entry,NULL,&dwType,(LPBYTE)data,&dwSize); の前に RegQueryValueEx(hKey,(LPCTSTR)Entry,NULL,&dwType,NULL,&dwSize); を実行する意味はないと思います。 もう一つ、細かいことですが、 char data[256]; とせずに、 char data[MAX_PATH]; とした方が良いと思います。 ( MAX_PATH は Windows.h の中で ( 厳密に言うと WinDef.h の中で ) #define MAX_PATH 260 と定義されています。)

maki55555
質問者

お礼

ご回答ありがとうございます。 ネットに掲載する上加工しており、そのミスでした、すいません。 2回行っているのは、Webで使い方を調べたときに、このような例があったのでそうしていました。 まずは戻り値の値を確認してみたいと思います。 またMAX_PATHに関するご指摘ありがとうございます。今はサンプルレベルでコードを組んでいますので、ちょっとその場限りの実装をしてしました。

関連するQ&A

  • レジストリ経由のフォント受渡し???

    数日前に類似の質問をさせて頂きました ご親切に3件もご指導の回答を頂きましたが、私の質問の仕方が悪く問題の解決に至っておりません 再度、質問形式を変更してお教えを請いたいと存じます C#のアプリケーションでフォントダイアログを表示してフォントを指定します 指定されたものをレジストリに書込みます FontDialog MyFont = new FontDialog(); if (MyFont.ShowDialog() != DialogResult.Cancel) { key = Registry.CurrentUser; key = key.CreateSubKey(@"MyCompany\MySoft"); key.SetValue("MyKey", MyFont.Font, Microsoft.Win32.RegistryValueKind.Unknown); ← (1) } レジストリの HKEY_CURRENT_USER ⇒ SoftWare ⇒ MyCompany ⇒ MySoft の下の MyKeyには REG_SZ 種類でデータとして [Font: Name=HPG行書体, Size=15.75, Units=3, GdiCharSet=128, GdiVericalFont=False] ← (2) と設定されました これをC++プログラムで読み込み、フォントダイアログで指定されたフォントで印刷します HKEY hKey; DWORD dwDisposition; LONG result; result = RegCreateKeyEx( HKEY_CURRENT_USER,L"MyCompany\\MySoft",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwDisposition); HFONT MyHFONT;  ← (3) result = RegQueryValueEx(hKey,L"MyKey",NULL,&dwType,NULL,&dwSize); //データのサイズを取得 result = RegQueryValueEx(hKey,L"MyKey",NULL,&dwType,(LPBYTE)(LPCTSTR)&MYHFONT,&dwSize); ← (4) SelectObject(hdc,MYHFONT); TextOutW (hdc, ~~  ← (5) 質問 (1) フォント指定をレジストリに書込む時、Unknown指定で良いのでしょうか  (2) Unknow指定で書込みましたがREG_SZ種別になっています OKですか それから書き込まれたデータはこれで正常ですか (3) HFONTを指定していますが、この場合OKですか (4) (LPBYTE)(LPCTSTR)&MYHFONTで受けていますが良いのでしょうか? (5) 最大のワカラナイ!!! 印刷された文字はC#のフォントダイアログでしていされたものに変化していない 以前のままです C++は初心者です 特にフォントのハンドリング知識は浅学です 宜しくご指導お願い申し上げます

  • 拾ってきたソースをうまくビルド出来ない

    正確に言うと、ソースの言語がC++なのかC#なのかわかりません。 おそらくC++だろうと思ってるのですが・・・。 #include <stdio.h> #include <string.h> #include <windows.h> int Time[5]={0}; DWORD GetRegInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, DWORD dwDefault) { BOOL bResult = FALSE; DWORD dwBuffer = 0; HKEY hOpenKey; if(RegOpenKeyEx(HKEY_CURRENT_USER, lpszSection, 0, KEY_EXECUTE, &hOpenKey) == ERROR_SUCCESS) { DWORD dwType; DWORD dwBufferSize = sizeof(DWORD); if(RegQueryValueEx(hOpenKey, lpszEntry, 0, &dwType, reinterpret_cast<LPBYTE>(&dwBuffer), &dwBufferSize) == ERROR_SUCCESS) { bResult = TRUE; } RegCloseKey(hOpenKey); } if(!bResult) { dwBuffer = dwDefault; } return dwBuffer; } void GetRegString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault, LPTSTR lpBuffer, DWORD nSize) { BOOL bResult = FALSE; HKEY hOpenKey; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszSection, 0, KEY_EXECUTE, &hOpenKey) == ERROR_SUCCESS) { DWORD dwType; DWORD dwBufferSize = nSize; if(RegQueryValueEx(hOpenKey, lpszEntry, 0, &dwType, reinterpret_cast<LPBYTE>(lpBuffer), &dwBufferSize) == ERROR_SUCCESS) { bResult = TRUE; } RegCloseKey(hOpenKey); } if(!bResult) { lstrcpyn(lpBuffer, lpszDefault, nSize); } } (文字制限を越えてしまったので、下半分を消しました) とりあえず、なにはともあれ試しにビルドしてみようと思い、bcc55でやってみました。 結果、.exeファイルと、.objともう一つ(名前忘れた)ができて、うまくできたかと思い、起動してみたのですが、DOSが開いてすぐ閉じてしまいます。 元々、このソースは既にビルドされた.exeファイルと一緒にアップロードされてたので、うまくいったらこういう動作をするっていうのは分かってたので、うまくビルドできてないのでしょう・・・。 そこで考えられる原因を考えたら、「言語が違う」これしか思いつきませんでした。 C#なのかもしれないと思い、Microsoft Visual C# Express Editionでも試してみましたが、これもうまくいかず、google先生に頼ってみましたが行き詰ってしまいました。 質問したい点を挙げます。 ・この言語はC++でしょうか?もしくはbcc32でコンパイル可能でしょうか? ・もし不可能な場合、どのコンパイラを使用すればうまくいくでしょうか?(できればフリーソフトでやりたいです)

  • レジストリ値の取得

    こんばんは。 レジストリ値の取得について教えてください。 下記のテストコードですが、これだけだとOKなのですが、いざ実際に使おうと他のソースに入れ込むと、一番最初(WinMain直後)に持ってきたとしても、「アプリケーションエラー」になってしまいます。 恐らくメモリの確保ができてないのかと思うのですがどうしたらよいのでしょうか? 環境は OS: Windows 2000 Professional C: Borland C++ Compiler です。 -- #include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HKEY hKey; LPBYTE lpData; LPDWORD lpcbData; lpData = (LPBYTE)malloc(256); RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", 0, KEY_QUERY_VALUE, &hKey); RegQueryValueEx(hKey, "BootDir", NULL, NULL, NULL, lpcbData); RegQueryValueEx(hKey, "BootDir", NULL, NULL, lpData, lpcbData); RegCloseKey(hKey); MessageBox(NULL, lpData, "lpData", MB_OK); return 0; }

  • 使用者名/組織名のエディットボックスへの表示方法

    Win XP PRO SP2、VC++6.0にてレジストリから使用者名/組織名を取得して、フォーム上の「表示」ボタンをクリックするとエディットボックスに表示するソフトを作成しています。 コンパイルもリンクも正常に出来ますが、フォームが表示されて「表示」ボタンをクリックすると、「問題が発生したため、registry_change.exe を終了します。 ご不便をおかけして申し訳ありません。」というウィンドウが表示されます。 どなたか教えて下さい。 よろしくお願いします。 下記が「表示」ボタンのコードです。 void CRegistory_changeView::OnButton1() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください CString ss; HKEY hRootKey; char EntryName1[256],EntryName2[256],KeyName[256],szBuff[256]; DWORD cbBuff; CEdit* myED1=(CEdit*)GetDlgItem(IDC_EDIT1); CEdit* myED2=(CEdit*)GetDlgItem(IDC_EDIT2); /* レジストリキーを開きます */ strcpy(KeyName, "Software\\Microsoft\\Windows NT\\CurrentVersion"); strcpy(EntryName1, "RegisteredOwner"); // 使用者名 strcpy(EntryName2, "RegisteredOrganization"); // 組織名 RegOpenKeyEx(HKEY_LOCAL_MACHINE, KeyName, 0, KEY_READ, &hRootKey); /* 実際にアクセスし文字列を取得します */ cbBuff = sizeof(szBuff); //(標準) RegQueryValueEx(hRootKey, EntryName1, NULL, NULL, (LPBYTE)szBuff, &cbBuff); myED1->SetWindowText((class CString &)cbBuff); RegQueryValueEx(hRootKey, EntryName2, NULL, NULL, (LPBYTE)szBuff, &cbBuff); myED2->SetWindowText((class CString &)cbBuff); RegCloseKey(hRootKey); }

  • RAID0に高速で書き込む方法(補足2)

    昨日から、たびたび質問させていただいています。 困っているので、教えてください。 下に、ハードディスクにデータを取り込むテストプログラムの一部を載せます。不必要と思われる部分は省かせていただいたので、少々バグが含まれていたり、変数の意味がわからないところがあるかもしれませんが、ご勘弁ください。 CFile file( m_strPath, CFile::modeCreate | CFile::modeReadWrite ); DWORD dwSize; dwSize = 2000000000; file.SetLength( dwSize ); file.SeekToBegin(); DWORD dwTick = GetTickCount(); DWORD aSize = 32 * m_dwSectorsPerCluster * m_dwBytesPerSector; char* buf = new char[ aSize ]; if( buf != NULL ) { DWORD pos; for( pos = 0; pos < dwSize; pos += aSize ) { file.Write( buf, aSize ); } CString str; str.Format( "%d ms for %g MB", GetTickCount() - dwTick, dwSize * 0.001 * 0.001 ); AfxMessageBox( str ); } 最後に書き込んだ大きさと、かかった時間を表示しています。 よろしくお願いします。

  • UTF_16で取得しUTF_8で出力したい!!

    こんにちは。 C言語初心者です。以前この件で質問させていただいたのですがエラーがとれず、もう一度質問してしまいました。 今回は、C言語でレジストリからデータをUTF_16で取得し、UTF_8で表示すると言うプログラミングを組みたいのですがどうしても下記のコードではエラーが出てしまいどうしていいかわかりません。 エラーの内容としては、16から8に変換する部分のutf8Sizeの部分で上手くいっていないようで、、、 どうしたらいいかわからないので、もし知っている方がいればよろしくお願いします。 #include<windows.h> #include<stdio.h> void QueryValue(void); int main(void){    QueryValue();    return 0; } void QueryValue(void){    HKEY hkey;    DWORD ValueType;    DWORD ValueSize;    wchar_t Value[1000];    char *utf8String = 0; // UTF-8 文字列バッファへのポインタ    size_t utf8Size = 0; // UTF-8 文字列のバイト数 (終端 NUL 含む) int result; // WideCharToMultiByte() の戻り値    /*レジストリキーのオープン*/    RegOpenKeyEx(      HKEY_LOCAL_MACHINE,         L"SOFTWARE\\Hitachi\\JP1/RemoteControlManager",      0,      KEY_ALL_ACCESS,      &hkey);     ValueSize = 1000;   /*レジストリ値の取得*/    RegQueryValueEx(      hkey,      L"ProgramName",      NULL,      &ValueType,      (LPBYTE)Value,      &ValueSize);    /*結果の表示(シフトJIS変換’%S’)*/    if(ValueType == REG_SZ) printf("%S\n",Value);    else printf("....can't read\n"); /*****************************************************/    //UTF_16からUTF_8変換を行う    result = WideCharToMultiByte(      CP_UTF8,      WC_NO_BEST_FIT_CHARS,      Value,      -1,      utf8String,      utf8Size,      NULL,      NULL);    if(result <= 0){      fprintf(stderr,"UTF_16→UTF_8変換エラー(%lu)\n",GetLastError());    }    /*結果の表示()*/    if(ValueType == REG_SZ) printf("%s\n",utf8String);    else printf("....can't read\n");    /*UTF_8文字列バッファを開放する*/    free(utf8String); /************************************************/    /*終了*/    RegCloseKey(hkey); }

  • RegQueryValueExでエントリ名にNullを指定するとエラー

    拡張子から、登録されているアプリケーションを探すために、レジストリを見ようとしています。 \HKEY_CLASSES_ROOT\<.拡張子> の中の、(標準)エントリの値を探し、 \HKEY_CLASSES_ROOT\探した名前\shell\open\command の中の、(標準)エントリで目的とするアプリケーションを見つけられるところまでは判ったのですが、 この最初のエントリ値を求めるところでつまづいています。 下記のような処理で、RegQueryValueExのところで必ずアプリケーションエラーが出てしまいます。 Dim tmpRet As Long Dim tmpKey As Long Dim tmpBuf As String Dim tmpBufLen As Long tmpRet = RegOpenKeyEx(HKEY_CLASSES_ROOT, ".txt", 0&, KEY_ALL_ACCESS, tmpKey) tmpBuf = String$(256, " ") tmpBufLen = 256 tmpRet = RegQueryValueEx(tmpKey, vbNullString, 0&, 0&, tmpBuf, tmpBufLen) tmpBuf = Left$(tmpBuf, tmpBufLen - 1) MsgBox ("データ値:" & tmpBuf)

  • RegQueryValueExについて

    Visual Studio C++ .NET 2003でレジストリの値を変更するコンソールアプリケーションを作りたいのですが、 RegQueryValueExで値を読み出すことができません。 下記のようにするとPathLenは正しく読み出せているのですが肝心のPathに何も格納されていないようです。 また4番目の引数はREG_SZが正しいように思えるのですがNULLでないと実行時に "ハンドルされていない例外:System.NullReferenceException:オブジェクト参照がオブジェクト インスタンスに設定されていません" というメッセージが出て途中終了してしまいます。 どなたかよろしくお願い致します。 long lRet; HKEY hkResult; CString Res; char Path[256]; long PathLen=0; //レジストリのハンドルと環境変数のレジストリをリードモードでオープン lRet = RegOpenKeyEx( HKEY_USERS, "S-1-5-21-842925246-1563985344-1957994488-500\\Environment", 0, KEY_ALL_ACCESS, &hkResult ); if(lRet == ERROR_SUCCESS) { //現在のパスを読み込む PathLen = strlen(Path); RegQueryValueEx( hkResult, "NEWVALUE", NULL, /*(LPDWORD)REG_SZ,*/NULL, (LPBYTE)Path, (LPDWORD)&PathLen ); } printf("%s\n", Path);printf("%ld\n", PathLen); //ハンドルをクローズ RegCloseKey(hkResult); インデントができなかったので見づらくてすみません。

  • レジストリのエクスポートについて教えてください

    開発環境 :eMbedded Visual C ++ 4.0 (SP4) 動作環境OS :WindowsCE 5.0 以上の環境でレジストリのエクスポートを行いたいのですが、うまく動作しません。 「RegSaveKey()」を使用しているのですが、「RegSaveKey()」を行った時点でエラー(50)が発生しエクスポートできません。 [例] HKEY hRegKey; // レジストリキー DWORD dwDisposition; // -------------------------------- coredll.dll ロード HMODULE hModule = LoadLibrary( _T("coredll.dll") ); // -------------------------------- RegSaveKeyアドレス取得 PFN_REGSAVEKEY pfnRegSaveKey = (PFN_REGSAVEKEY)GetProcAddress( hModule, _T("RegSaveKey") ); if ( NULL == pfnRegSaveKey ) { // -------------------------------- coredll.dll アンマップ FreeLibrary( hModule ); return ; } // -------------------------------- レジストリキー オープン dwRet = RegCreateKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE", 0, NULL, REG_OPTION_BACKUP_RESTORE, KEY_ALL_ACCESS, NULL, &hRegKey, &dwDisposition); if( dwRet == ERROR_SUCCESS ) { dwRet = pfnRegSaveKey( hRegKey, L"\\registry.reg", NULL ); } // -------------------------------- coredll.dll アンマップ FreeLibrary( hModule ); // -------------------------------- レジストリキー クローズ RegCloseKey(hRegKey); Windows CEでのレジストリ関係をいろいろ調べたのですが解決できませんでした。詳しい方、アドバイスをよろしくお願いします。

  • 読み込んだBMPデータの行方

    参考書を元にBMPを読み込み、 BYTE*型にデータを移して、画像処理や転送に利用できるようにしたいのですが、 どこに画像データの実体が有るのかがよくわかりません・・。 ---------- static LPBYTE lpDIB = NULL; static LPBITMAPINFO lpbiInfo; static LPDWORD lpPixel; LPBYTE lpBMP; LPBITMAPINFOHEADER lpbiBMPInfo; LPBYTE lpBMPPixel; BYTE* ppp; static int iWidth, iHeight, iLength; int iFileSize; DWORD dwOffset; int i, j; HANDLE fhBMP; DWORD dwRead; HDC hdc; PAINTSTRUCT ps; /*BMP取得*/ //ファイルオープン fhBMP = CreateFile("test.bmp", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (fhBMP == INVALID_HANDLE_VALUE) { MessageBox(NULL, "test.bmpが見つかりません。", "エラー", MB_OK); return 0; } //ファイルサイズ取得 iFileSize = GetFileSize(fhBMP, NULL); //ファイル読み込みバッファ確保 lpBMP = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, iFileSize); //ファイル読み込み ReadFile(fhBMP, lpBMP, iFileSize, &dwRead, NULL); //ファイルを閉じる CloseHandle(fhBMP); //BMP内のBITMAPINFO取得 lpbiBMPInfo = (LPBITMAPINFOHEADER) (lpBMP + sizeof(BITMAPFILEHEADER)); //先頭からピクセル列までのオフセット取得 dwOffset = *(LPDWORD)(lpBMP + 10); //BMP内ピクセル列の先頭アドレス計算 lpBMPPixel = lpBMP + dwOffset; //ビットマップの大きさ取得 iWidth = lpbiBMPInfo->biWidth; iHeight = lpbiBMPInfo->biHeight; //BMPピクセル列の1ラインの長さを計算 if (iWidth % 4 == 0) { iLength = iWidth * 3; } else { iLength = iWidth * 3 + (4 - (iWidth * 3) % 4); } //DIB用バッファを確保 lpDIB = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFO) + iWidth * iHeight * 4); //DIB用ポインタ分配 lpbiInfo = (LPBITMAPINFO)lpDIB; lpPixel = (LPDWORD)(lpDIB + sizeof(BITMAPINFO)); //BITMAPINFO設定 lpbiInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpbiInfo->bmiHeader.biWidth = iWidth; lpbiInfo->bmiHeader.biHeight = iHeight; lpbiInfo->bmiHeader.biPlanes = 1; lpbiInfo->bmiHeader.biBitCount = 32; lpbiInfo->bmiHeader.biCompression = BI_RGB; //BMP内のピクセル列を32ビット化してコピー for (i = 0;i < iHeight;i++) for (j = 0;j < iWidth; j++) CopyMemory(lpPixel + j + i * iWidth, lpBMPPixel + j * 3 + i * iLength, 3); //ファイル読み込みバッファ解放 HeapFree(GetProcessHeap(), 0, lpBMP); /*描画*/ hdc = BeginPaint(hWnd, &ps); //DIBをウインドウのDCに描画 StretchDIBits(hdc, 0, 0, iWidth, iHeight, 0, 0, iWidth, iHeight, lpPixel, lpbiInfo, DIB_RGB_COLORS,SRCCOPY); EndPaint(hWnd, &ps); ---------- 描画部分のStretchDIBits()を調べて lpPixelに格納されているように思えたのですが、これはただのDWORDですし。 lpBMPPixelだとしても、描画では全く使われていないのが不可解で。 なぜこう(描画にDWORD)なっているのでしょうか? どこに画像データが有るのでしょうか?

専門家に質問してみよう