ホーム » Windows (ページ 7)
「Windows」カテゴリーアーカイブ
::GetDiskFreeSpaceEx , ::statvfs
Win9x が多く存在していた頃のコードの MFC を使用しない方法での書き直し.
前のものは次の様になっている.
// J048221 SDK32:GetDiskFreeSpace と GetDiskFreeSpaceEx について
typedef BOOL (WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER,PULARGE_INTEGER, PULARGE_INTEGER);
// ..
fResult = ::GetDiskFreeSpace(pszDrive,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters) ;
if (fResult) {
TotalBytes = (__int64)TotalClusters * SectorsPerCluster * BytesPerSector ;
TotalFreeBytes = (__int64)FreeClusters * SectorsPerCluster * BytesPerSector ;
FreeBytesAvailable = TotalFreeBytes ;
}
// ..
{
P_GDFSE pGetDiskFreeSpaceEx = NULL;
#ifdef UNICODE
pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")),"GetDiskFreeSpaceExW") ;
#else
pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")),"GetDiskFreeSpaceExA") ;
#endif
if (pGetDiskFreeSpaceEx) {
fResult = pGetDiskFreeSpaceEx (pszDrive,
(PULARGE_INTEGER)&FreeBytesAvailable,
(PULARGE_INTEGER)&TotalBytes,
(PULARGE_INTEGER)&TotalFreeBytes);
}
}
https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/231497
Windows 環境では次の様な感じ?
class DiskFree {
public:
DiskFree () { Free = Total = 0 ; }
public:
u_64 Free ;
u_64 Total ;
} ;
DiskFree GetDiskFree (LPCTSTR path)
{
DiskFree df ;
u_64 freeC = 0 ;
u_64 free = 0 ;
u_64 total = 0 ;
if (::GetDiskFreeSpaceEx(path,(PULARGE_INTEGER)&freeC,(PULARGE_INTEGER)&total,(PULARGE_INTEGER)&free)) {
df.Free = free ;
df.Total= total;
}
return df ;
}
Linux 環境では ::statvfs が使えるみたいで,次の様なコードで取得してデバッガで確認.
#include <iostream>
#include <sys/statvfs.h>
int main()
{
struct statvfs vfs = { 0 } ;
::statvfs(".", &vfs) ;
return 0 ;
}
vfs {...} statvfs
f_bsize 4096 unsigned long
f_frsize 4096 unsigned long
f_blocks 1452408524 __fsblkcnt_t
f_bfree 200259802 __fsblkcnt_t
f_bavail 199469255 __fsblkcnt_t
f_files 183001088 __fsfilcnt_t
f_ffree 181248356 __fsfilcnt_t
f_favail 181248356 __fsfilcnt_t
f_fsid 3941329918106335254 unsigned long
f_flag 4096 unsigned long
f_namemax 255 unsigned long
__f_spare int [6]
[0] 0 int
[1] 0 int
[2] 0 int
[3] 0 int
[4] 0 int
[5] 0 int
Iwao@AS5202T:/volume1/home/Iwao $ cd gcc_test/Test/t_linux/T_vfs/T_s_vfs/
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/T_vfs/T_s_vfs $ ll
total 12
drwxrwxrwx 2 Iwao users 4.0K Jul 1 22:01 ./
drwxrwxrwx 4 Iwao users 4.0K Jul 1 22:00 ../
-rwxrwxrwx 1 Iwao users 581 Jul 1 21:55 T_s_vfs.cpp*
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/T_vfs/T_s_vfs $ cat T_s_vfs.cpp
#include <iostream>
#include <clocale>
#include <sys/statvfs.h>
#include "_tdefine.hxx"
#include "t_tstrng.hxx"
int _tmain (int argc,TCHAR* argv[])
{
_tsetlocale(LC_ALL,_T("")) ;
{
struct statvfs vfs = { 0 } ;
if (::statvfs(".", &vfs) == 0) {
u_64 free = vfs.f_bavail * vfs.f_frsize ;
u_64 total= vfs.f_blocks * vfs.f_frsize ;
std::tout << ::To_tstring_Ki(free) << _T(" / ") << ::To_tstring_Ki(total) << std::endl ;
std::tout << ::To_tstring_cs(free) << _T(" / ") << ::To_tstring_cs(total) << std::endl ;
}
}
return 0 ;
}
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/T_vfs/T_s_vfs $ g++ T_s_vfs.cpp -Wall
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/T_vfs/T_s_vfs $ ./a.out
760.90 G / 5.41 T
817,005,420,544 / 5,949,065,314,304
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/T_vfs/T_s_vfs $
SHBrowseForFolder
今度はフォルダの参照.
ダイアログを表示するだけの最低限のコード.
#include <ShlObj.h>
bool Test (void)
{
BROWSEINFO bi = { 0 } ;
LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi) ;
if (pidl == NULL) { return false ; }
::CoTaskMemFree(pidl) ;
return true ;
}
int main (void)
{
while (true) {
if (!Test()) {
break ;
}
}
return 0 ;
}
BROWSEINFO の hwndOwner も指定していないので動作がモードレスになってしまう.
SHBrowseForFolder のドキュメントを見ると IFileDialog FOS_PICKFOLDERS とある.
選択したフォルダ名を戻すように変更.
tstring SH_GetPathFromIDList (LPCITEMIDLIST pidl)
{
tstring path ;
path.resize(MAX_PATH+10) ;
BOOL result = ::SHGetPathFromIDList(pidl,&path[0]) ;
return path.c_str() ;
}
tstring Test (void)
{
BROWSEINFO bi = { 0 } ;
bi.ulFlags |= BIF_RETURNONLYFSDIRS ;
bi.ulFlags |= BIF_NEWDIALOGSTYLE ;
bi.ulFlags |= BIF_NONEWFOLDERBUTTON ;
LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi) ;
if (pidl == NULL) { return tstring() ; }
tstring path = ::SH_GetPathFromIDList(pidl) ;
::CoTaskMemFree(pidl) ;
return path ;
}
pszDisplayName を指定すると,選択されたフォルダ名が返る.
tstring disp_name ;
disp_name.resize(MAX_PATH) ;
bi.pszDisplayName = &disp_name[0] ;
// ... SHBrowseForFolde
std::tout << disp_name.c_str() << std::endl ;
初期フォルダ指定の追加.
int CALLBACK SH_BrowseCallback (HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData)
{
switch (uMsg) {
case BFFM_INITIALIZED :
::SendMessage(hwnd,BFFM_SETSELECTION,1,(LPARAM)(LPCTSTR)lpData) ;
return 1 ;
break ;
default :
return 0 ;
break ;
}
return 0 ;
}
{
// ...
tstring init_fold = init_fold_ ;
// ...
bi.lpfn = SH_BrowseCallback ;
bi.lParam = (LPARAM)init_fold.c_str() ;
LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi) ;
// ...
}
Win10 に VS 6 インストール
今まで仮想マシンの WinXP で VC 6 を使用してきたが,ちょっと面倒なので Win10 環境に入れてみた.
使用したのは次の ISO .
en_visual_studio_6.0_professional_x86_dvd_224df581.iso
2021/04 に VS のダウンロードサイトで見つけた.
その時 Win7 環境などにインストールして動作することは確認済み.
インストール時,データベース関連を入れると止まると書かれていたので,外してインストール.
VB6開発環境をWindows 10にインストールする手順
VC 6 を簡単に確認した限りは何とか使えそう.
Win11 に VS 6 のインストール
Win11 22H2(デバッグできない時の設定も書いています)
2024/04/29
Win10 ,Win11 共に一部の制限があるものの VC 6 は特に問題なく使えている.
VC 6 から VC 2005 への移行
vc 6 から VC 201x への移行
vc 6 から VC 2022 への移行
OPENFILENAME
コンソール AP では,標準入力を使用していた.
#include "quotm.hxx"
#include "existff.hxx"
inline bool Test (void)
{
while(true) {
tstring str ;
{
tstring buf ;
buf.resize(1000) ;
std::terr << _T("file ...=") ;
std::tin.getline(&buf[0],std::streamsize(buf.size())) ;
str = buf.c_str() ;
if (str == _T("q")) { break ; }
else if (str == _T("Q")) { break ; }
str = ::QuotM_Del_All(str) ;
if (str.empty()) { continue ; }
}
{
if (::File_IsNothing(str)) { continue ; }
std::tout << str << std::endl ;
}
}
return true ;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
{
Test() ;
}
return 0 ;
}
以前作成した CFileDialog を使用したもの.
#include <afxwin.h>
#include "F_Dialog.hxx"
#include "quotm.hxx"
inline bool Test (void)
{
while(true) {
tstring str ;
{
str = ::FD_GetOpenFile(_T("./")) ;
if (str.empty()) { break ; }
}
{
if (::File_IsNothing(str)) { continue ; }
std::tout << str << std::endl ;
}
}
return true ;
}
CWinApp theApp;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) {
std::terr << _T("error : AfxWinInit") << std::endl ;
nRetCode = 1;
}
else {
Test() ;
}
return nRetCode;
}
////////////////////////////////////////////////////////////////////////////////////////
#include <AfxExt.h>
#include "BrowseFF.cxx"
「開く」ダイアログを表示するだけのコード.
{
OPENFILENAME ofn = { 0 } ;
ofn.lStructSize = sizeof(OPENFILENAME) ;
if (!::GetOpenFileName(&ofn)) { return tstring() ; }
// ...
}
OPENFILENAME の指定が複雑なので,使いそうな内容でまとめてみた.
OPENFILENAME | |
lStructSize | sizeof(OPENFILENAME) |
hwndOwner | NULL の時,モードレスになる. CFileDialog では DoModal で求めている. |
lpstrFile | 選択されたファイル名が入る. OFN_ALLOWMULTISELECT の場合は,下のメモリイメージ. |
nMaxFile | lpstrFile で確保している領域の文字数 |
OFN_ALLOWMULTISELECT の場合の結果の lpstrFile .
0x02C00078 44 3a 5c 44 6f 63 75 6d 65 6e 74 5c 56 53 5c 56 D:\Document\VS\V 0x02C00088 53 5c 32 30 30 35 5c 54 5f 4f 70 65 6e 46 5c 54 S\2005\T_OpenF\T 0x02C00098 5f 4f 46 5f 4d 46 43 54 5f 4f 46 5f 4d 46 43 _OF_MFC.T_OF_MFC 0x02C000A8 2e 42 41 4b 54 5f 4f 46 5f 4d 46 43 2e 63 70 .BAK.T_OF_MFC.cp 0x02C000B8 70 54 5f 4f 46 5f 4d 46 43 2e 76 63 70 72 6f p.T_OF_MFC.vcpro 0x02C000C8 6a 54 5f 4f 46 5f 4d 46 43 2e 76 63 70 72 6f j.T_OF_MFC.vcpro 0x02C000D8 6a 2e 5a 31 37 30 53 30 2e 49 77 61 6f 2e 75 73 j.Z170S0.Iwao.us 0x02C000E8 65 72 00 00 00 00 00 00 00 00 00 00 00 00 er.............. 0x027E6B50 44 00 3a 00 5c 00 44 00 6f 00 63 00 75 00 6d 00 65 00 6e 00 74 00 5c 00 56 00 53 00 5c 00 56 00 D:\Document\VS\V 0x027E6B70 53 00 5c 00 32 00 30 00 30 00 35 00 5c 00 54 00 5f 00 4f 00 70 00 65 00 6e 00 46 00 5c 00 54 00 S\2005\T_OpenF\T 0x027E6B90 5f 00 4f 00 46 00 5f 00 4d 00 46 00 43 00 00 00 54 00 5f 00 4f 00 46 00 5f 00 4d 00 46 00 43 00 _OF_MFC.T_OF_MFC 0x027E6BB0 2e 00 42 00 41 00 4b 00 00 00 54 00 5f 00 4f 00 46 00 5f 00 4d 00 46 00 43 00 2e 00 63 00 70 00 .BAK.T_OF_MFC.cp 0x027E6BD0 70 00 00 00 54 00 5f 00 4f 00 46 00 5f 00 4d 00 46 00 43 00 2e 00 76 00 63 00 70 00 72 00 6f 00 p.T_OF_MFC.vcpro 0x027E6BF0 6a 00 00 00 54 00 5f 00 4f 00 46 00 5f 00 4d 00 46 00 43 00 2e 00 76 00 63 00 70 00 72 00 6f 00 j.T_OF_MFC.vcpro 0x027E6C10 6a 00 2e 00 5a 00 31 00 37 00 30 00 53 00 30 00 2e 00 49 00 77 00 61 00 6f 00 2e 00 75 00 73 00 j.Z170S0.Iwao.us 0x027E6C30 65 00 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 er.............. lpstrFile 0x02c10078 "D:\Document\VS\VS\2005\T_OpenF\T_OF_MFC\ReadMe.txt" char *
デバッガで OPENFILENAME_SIZE_VERSION_400 となる様にしたもの.
MFC 9 で bVistaStyle を FALSE とすると
VC 8 exe と同様の,左側がフォルダツリーではない表示のもの.
デフォルトの TRUE だと
COM を利用したもの?
Common Item Dialog
今度は MFC を使用しない方法.
::GetOpenFileName を使用する方法で OFN_ALLOWMULTISELECT を指定すると実行されなかった.
見た目のエラーにはならない?が,API を呼んで FALSE で抜けてくる.
::CommDlgExtendedError で調べると FNERR_INVALIDFILENAME だった.
存在しないファイル名などを与えるとうまくないみたい.
まだ何か足りないみたいで Win3.x 頃の表示になってしまった.
選択したファイル名などもスペースで区切られている.
OFN_ALLOWMULTISELECT を指定する時は OFN_EXPLORER も指定する必要があるみたい.
次の所に書かれていた.
OPENFILENAMEW structure (commdlg.h)
OFN_ALLOWMULTISELECT | OFN_EXPLORER の場合 lpstrFile に存在しないファイル名でも問題なさそう.
複数選択可能な「開く」ダイアログのコードは次の様な感じ.
tstring GetOpenFile (LPCTSTR default_name=_T("./"))
{
HWND hwnd = ::GetConsoleHwnd() ;
tstring str_file = default_name ;
str_file.resize(260*100) ;
OPENFILENAME ofn = { 0 } ;
{
ofn.lStructSize = sizeof(OPENFILENAME) ;
ofn.hwndOwner = hwnd ;
ofn.nMaxFile = DWORD(str_file.size()) ;
ofn.lpstrFile = &str_file[0] ;
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_HIDEREADONLY ;
}
if (!::GetOpenFileName(&ofn)) {
DWORD err = ::CommDlgExtendedError() ;
std::terr << ::To_tstring(u_32(err),16) << std::endl ;
return tstring() ;
}
tstring sel_file ;
{
sel_file = ofn.lpstrFile ;
// ...
}
return sel_file ;
}
拡張子のフィルタなどは指定していない.また,選択されたファイルを取得するコードもこれから.
選択されたファイルを取得するコード.
tstring String_Change (c_tstring& str_,const TCHAR src,const TCHAR dst)
{
tstring str = str_ ;
for (size_t index=0 ; index<str.size() ; index++) {
TCHAR ch = str[index] ;
if (ch == src) {
str[index] = dst ;
}
}
return str ;
}
tstring sel_file ;
{
sel_file = ofn.lpstrFile ;
sel_file = str_file ;
sel_file = ::String_Change(ofn.lpstrFile,_T('\x0'),_T('\n')) ;
sel_file = ::String_Change(str_file, _T('\x0'),_T('\n')) ;
sel_file = ::String_TrimBoth(sel_file) ;
}
ofn.lpstrFile は ASCIIZ となってしまうので,str_file をそのまま使用する必要がある.
Win3.x 形式の lpstrFile のダンプ.
0x02311F00 0043 003a 005c 0055 0053 0045 0052 0053 005c 0050 0055 0042 004c 0049 0043 005c C.:.\.U.S.E.R.S.\.P.U.B.L.I.C.\.
0x02311F20 0044 004f 0043 0055 004d 0045 004e 0054 0053 005c 0020 0042 0061 0063 006b 0043 D.O.C.U.M.E.N.T.S.\. .B.a.c.k.C.
0x02311F40 0050 002e 0062 0061 0074 002e 006c 006e 006b 0020 0057 0049 004e 0031 0030 002d P...b.a.t...l.n.k. .W.I.N.1.0.-.
0x02311F60 007e 0031 002e 004c 004e 004b 0020 005a 0031 0037 0030 0044 004f 007e 0031 002e ~.1...L.N.K. .Z.1.7.0.D.O.~.1...
0x02311F80 004c 004e 004b 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 L.N.K...........................
区切りがスペースになるため,ファイル名などにスペースが含まれている場合は 8.3 形式 になる.
lpstrFilter を指定.
tstring filter ;
filter += _T("Executable Files (*.exe)|*.exe|") ;
filter += _T("All Files (*.*)|*.*|") ;
filter += _T("|") ;
filter = ::String_Change(filter,_T('|'),_T('\x0')) ;
OPENFILENAME ofn = { 0 } ;
{
ofn.lStructSize = sizeof(OPENFILENAME) ;
// ...
ofn.lpstrFilter = &filter[0] ;
}
コンソール AP のウィンドウハンドル
GetOpenFileName を調べていて,コンソール AP のウィンドウハンドルが必要になった.
ofn.hwndOwner の NULL の指定では,モードレスの動作になってしまう.
CFileDialog は DoModal 内で設定していて,通常の AP であればうまく動作する様になっている.
「コンソール AP ウィンドウハンドル」で検索すると次のものがあった.
How to obtain a Console Window Handle (HWND)
そこにあったサンプルを,関数として抜き出し.
con_wnd.hxx
2023/08/02
2023/03 に ::GetConsoleWindow を使用したので,その関連のまとめ.
VC 7 以降,WinCon.h に ::GetConsoleWindow が追加されている.
それで,con_wnd.hxx では VC 6 やそれ以降のものでもうまく通る様に変更している.
Win10 に GLUT インストール
2 年位前に Linux 環境 での GLUT はインストール した.
今回は Win10 環境に…
「Windows GLUT」で検索すると…
なかなかうまく書かれているものが見つからない.
次の所は古いまま?
GLUT – The OpenGL Utility Toolkit
以前見た時は更新されていない様に思ったが…
freeglut
そこからのリンク
freeglut Windows Development Libraries
その中の freeglut 3.0.0 MSVC Package が欲しかったもの.
…/bin/freeglut.dll を c:\Windows\SysWOW64 にコピー.
また,glut32.dll の頃の exe も動作する様に …\SysWOW64\glut32.dll としてもコピー.
…/bin/x64/freeglut.dll は c:\Windows\System32 にコピー.
これで,以前作成した exe がそのまま動作することを確認.
glut.h と freeglut*.h は,次の …\PlatformSDK\include\gl にコピー.
VC 8 C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\Include\gl
VC 9 C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\gl
VC10 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\gl
VC11 C:\Program Files (x86)\Windows Kits\8.0\Include\um\gl
VC12 C:\Program Files (x86)\Windows Kits\8.1\Include\um\gl
VC14 C:\Program Files (x86)\Windows Kits\8.1\Include\um\gl
VC141 C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\gl
VC142 C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\gl
freeglut.lib は次の所にコピー.
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\Lib
C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib
C:\Program Files (x86)\Windows Kits\8.0\Lib\win8\um\x86 , x64
C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86 , x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86 , x64
2021/12/24
glut.h と freeglut*.h,freeglut.lib のコピー先は,お使いの環境によって異なります.
10.0.19041.0 は 2021/05 の頃での設定によるものです.
2021/12 では,10.0.22000.0 にコピーする必要があります.
https://itl.mish.work/Iwao/Doc/algo/to_thick/glut.htm
2023/11/02
VC インクルードパスの確認方法
2024/07/25
サンプルのコードを用意.t_c_ut_2024_07_25.zip
VC 6 ではそのままビルドできます.VC 2019 までは dsp からのアップグレードで可能です.
Linux 環境では次の様に入力して a.out の出力が可能です.
g++ t_c_ut_1.cpp -lGL -lGLU -lglut
「iPhone 3D プログラミング」にあるコードを使用しています.
MDI exe が動作しない?
Win10 Insider Preview 21H1 環境で,幾つかの exe がうまく動作しない.
VC 8 でビルドした exe は OK .VC 10 以降は NG のものがある.
SDI exe は大丈夫そうで,MDI exe はすべてではないが NG のものが多い.
タイミングとしては,3D データを読み込んだ後,ウィンドウに表示する前.
2021/07/12
一度「開く」ダイアログを表示するとその後はうまく動作する.
SDI exe であっても,VC 14 MFC スタティックだとうまくない?
これはプロジェクトの設定がまずかったためで,別の記事に.
2021/04/01
ちょっとわからないので,リモートデバッグの環境を作成することに.
MSDN Visual Studio での C++ プロジェクトのリモート デバッグ
リモートツールをダウンロードして,インストール.「スタート」から「Remote Debugger」を起動.
リモート側で exe を実行して,ホスト側で「アタッチ」.
2021/04/02
原因は,CRecentFileList::Add を通った時 ::CoInitinalize が呼び出されていないため.
どうも MFC 10 から?変わったみたい.
MS C++ executable just started failing
MFC application crashing in ProcessShellCommand() when file to open specified on command line
それでも,なぜ環境によっては表面化しないのか?
CRecentFileList::Add で Win7 以降の「ジャンプリスト」に登録(::SHAddToRecentDocs )する様になった.
Win10 20H2 でも現象は発生した.2004 では問題ない.
対応としては InitInstance の最初に以下を追加.
// OLE ライブラリを初期化します。
if (!AfxOleInit()) {
AfxMessageBox(_T("OLE の初期化に失敗しました。")) ;
return FALSE ;
}
2021/04/06
2016/夏頃の Win10 で,その様になるものが存在したみたい.
その頃は T90Chi + VC 2015 + i3DV でやっていたと思うが,気づかなかった?
VC コンソール AP にリソースの追加
先日作成したコンソール AP に,バージョン情報などを埋め込みたいと思い調べてみた.
検索すると次の所があった.
MSDN リソースを作成する (C++)
「Win32 コンソール アプリケーション」を「空のプロジェクト」として作成.
コードは,個人的な雛型 をコピーしてプロジェクトに登録.
#include <clocale> #include <iostream> #include "i_define.hxx" int _tmain(int argc, TCHAR* argv[]) { _tsetlocale(LC_ALL, _T("")); { std::tout << _T("hello") << std::endl; } return 0; }
「ソリューション エクスプローラー」の「プロジェクト」を「右クリック」-「追加」-「新しい項目」.
「リソース ファイル (.rc)」を選択,ファイル名を指定して「追加」.
「リソース ビュー」に切り替わるので,ツリーの「~.rc」の所を「右クリック」して「リソースの追加」.
必要に応じてアイコンなども追加.
ビルドすると exe に付加されている.
2022/08/01
バージョンリソースの読込み
FVersion.hxx
SDI exe でファイルのドロップ
SDI exe でファイルをドロップされた時,関連する異なるファイルを開きたくなった.
次の様に,変換済みのデータが存在している時はそれを対象とする.
https://dev.mish.work/wordpress/2021/03/03/win-prevent-2nd/
ドキュメントクラスの OnOpenDocument で変更するのは可能だが「MRU ファイル リスト」に残ってしまう.
15 年位前に,ブラウザからリンクをドロップして動作させるコードを書いた.
最近のブラウザでは,当時の様な操作はできないみたい.
WM_DROPFILES でリンクのテキストが取れたのだったと思う.
この時,何を参考にしてここにたどり着いたかは不明.
それを見ると CMainFrame::OnDropFiles にコードが書いてある.
デフォルトのコードとしては,CFrameWnd::OnDropFiles を呼出している.
::DragQueryFile でファイル名を取って CWinApp::OpenDocumentFile を呼出している.
CMainFrame::OnDropFiles でファイル名を取った後,処理を追加して CWinApp::OpenDocumentFile を呼べば良い.
手順としては (VC)\…\atlmfc\src\mfc\winfrm.cpp の CMainFrame::OnDropFiles をコピーして編集している.
void CMainFrame::OnDropFiles(HDROP hDropInfo) { SetActiveWindow(); // activate us first ! CWinApp* pApp = AfxGetApp(); ASSERT(pApp != NULL); v_tstring files = ::DropFilesTo(hDropInfo) ; if (files.size() > 0) { tstring file = files[0] ; // ここで,必要に応じてファイル名を変更するなどの処理 pApp->OpenDocumentFile(file.c_str()) ; } ::DragFinish(hDropInfo); // CFrameWnd::OnDropFiles(hDropInfo); }
今回は SDI なのでこんな感じ.MDI であればループで回せば良い.
仮想マシンの XP が遅くなった?
今はもう誰も必要ないと思う情報.
先日 WinXP の VHD が入っている HDD が壊れて交換.
その時,ついでに PC のメモリも増設している.
壊れかけた HDD には不良セクタがあった様だが,対象の VHD は大丈夫だった.
デュプリケーターでコピーして,それなりに動作していると思う.
その後,仮想マシンの WinXP の動作が遅くなった?
全体的に遅いのではなく,メッセージボックスが出る時に数秒止まる様な感じ.
何が原因かしばらくわからなかった.
ホストのメモリに余裕がでたので,仮想マシンのメモリの割り当てを増やした.
この仮想マシンは 1.5G だったのを 3G に.
これがいけなかったみたいで,2G にすることで前の状態に戻ったと思われる.
これは関係なかった.再起動による一時的な解消.
「仮想マシンの状態を保存」をすると解消される?
2021/03/14
遅くなるのは,音が出る時.使っているうちに音が再生されるまでのタイムラグが大きくなる.
使い勝手は良くないが,
VirtualBox の「仮想マシンの状態を保存」で解消できることを確認.
「一時停止」では効果はない.
Win 環境で 2 重起動の禁止
ライブラリとして提供されている部分を,他のコードと分離するためコンソール AP(変換 exe)として作成.
テスト用にそれを呼出す部分も別のコンソール AP(呼出 exe)として作成.
変換 exe は,aaa.dat を aaa.txt の様に異なる形式に変換する機能.
呼出 exe は,::ShellExecute(…,”変換.exe aaa.dat”,…) の様に呼出し aaa.txt を処理する.
データにより変換(*.dat から *.txt へ)時間は数秒から数時間.
変換できたかどうかをチェックしている部分は次の様なコード.
for (size_t index=0 ; index<1000 ; index++) { ::Sleep(100) ; if (::File_IsExist(g3d_name)) { break ; } }
データが悪いのか,ライブラリの問題なのかは不明たが,変換 exe の中でエラーになってしまうことがある.
エラーを軽減する方法はわかっているが,それでも完全ではない.
同じデータでも通る時とそうでないことがあり不安定.
そのため,変換後データが存在しない時に,変換中でなければ「変換 exe」を再起動させなければならない.
2021/03/09
ここまでの部分を単体のコードとして作成.
t_call.cpp
t_conv.cpp
T_mtex_2021_03_09.zip
これらのコードでの問題は,
* 異常終了が判断できない.
* 変換に時間がかかる時,複数回呼んでしまう.
起動しているかどうかは Mutex を使えば良さそう.
変換 exe が起動している間,::CreateMutex (…,”入力ファイル名”) で作成したものを保持する.
呼出 exe のループでは,その Mutex が存在するかチェック.
なくなった時に,出力ファイルが存在している時はループを抜ける.
出力ファイルが存在していない時は,もう一度「変換 exe」を呼出す.
今まで作成の Mutex を使用したコード.
Prevent2.hxx Prevent2.cxx
ExclusS.hxx
t_conv.cpp
bool test (const tstring& name_in_) { tstring f_name = ::Path_GetName(name_in_) ; HANDLE hMutex = ::CreateMutex(NULL,FALSE,f_name.c_str()) ; time_t now = ::time(NULL) ; if ((now % 3) == 0) { ::Sleep(3000) ; tstring name_out = name_in_ + _T(".out") ; tstring name_uni = ::Get_unique_name(name_out) ; ::File_CreateEmpty(name_uni) ; } else { ::Sleep(500) ; } ::CloseHandle(hMutex) ; return true ; }
t_call.cpp
bool t_call (c_tstring& in_name_) { tstring name_in_ = in_name_ ; { tstring f_name = ::Path_GetName(name_in_) ; HANDLE hMutex = ::CreateMutex(NULL,FALSE,f_name.c_str()) ; DWORD error = ::GetLastError() ; ::CloseHandle(hMutex) ; if (error == ERROR_ALREADY_EXISTS) { return true ; } } tstring this_exe = ::i_GetModuleFileName() ; tstring conv_exe = ::Path_AddLastSP(::Path_GetDir(this_exe)) + _T("t_conv.exe") ; name_in_ = ::QuotM_Add_Auto(name_in_) ; // ... // 変換 exe を起動 // ... return true ; }
2021/03/10 更にクラスに.W_mutex.hxx
次の様にできる.
bool test (const tstring& name_in_) { W_mutex mutex(::Path_GetName(name_in_).c_str()) ; time_t now = ::time(NULL) ; if ((now % 3) == 0) { ::Sleep(3000) ; tstring name_out = name_in_ + _T(".out") ; tstring name_uni = ::Get_unique_name(name_out) ; ::File_CreateEmpty(name_uni) ; } else { ::Sleep(500) ; } return true ; } bool t_call (c_tstring& in_name_) { tstring name_in_ = in_name_ ; { W_mutex mutex(::Path_GetName(name_in_).c_str()) ; if (mutex.Is_exist()) { return true ; } } tstring this_exe = ::i_GetModuleFileName() ; tstring conv_exe = ::Path_AddLastSP(::Path_GetDir(this_exe)) + _T("t_conv.exe") ; name_in_ = ::QuotM_Add_Auto(name_in_) ; // ... return true ; }
2021/12/01
W_mutex を利用した単体テスト用コード
VirtualBox BLKCACHE_IOERR
今まで特に問題なく使えていた VHD が今日の午前中から調子が悪い.
仮想マシンの実行中にエラーが発生しました!エラーの詳細を以下に示します。説明されたエラーを修正し、仮想マシンの再実行することができます。 The I/O cache encountered an error while updating data in medium "ahci-0-0" (rc=VERR_IO_CRC). Make sure there is enough free space on the disk and that the disk is working properly. Operation can be resumed afterwards. エラーID: BLKCACHE_IOERR 重要度: 致命的でないエラー
検索すると「ホストの I/O キャッシュを使う」とあったが…
チェックを付けて起動させると,
どうも違うみたいで,元に戻した.
2021/02/28
どうも物理ディスクに障害が発生しているみたい.
突然ホストがブルースクリーンに.
起動後,ディスクの状態が「注意」となっていて「代替処理保留中のセクタ数」の所が黄色に.
イベントビューアを見ると disk のエラーがいっぱい.
さかのぼって調べるとさらに 1 週間前位にもあり.
D ドライブのものをバックアップしていて,対象の VHD をコピーしている時読み取りエラーとなった.
最近,ホストの Windows Update 後などの再起動が遅いと感じていたが,この辺りが原因だったか?
PC の内蔵ディスクが壊れた?
CMutex の使用でデッドロック?
何年も前(2015/11?)からなのかもしれないが,
今の PC になってから作成した exe が起動時やサムネイルの表示などで停止する現象が時々発生している.
発生する頻度が低いのと,現象が絞り切れていなかったのでそのままになっていた.
今日,デバッグしていると exe が起動しない.
その時までに起動済みのものは動作しているが,止まってしまうものもあり.
以前この現象が発生した時は再起動することで回避したが,今回はもう少し調べてみることにした.
デバッガで追いかけると CMutex の Lock(INFINITE) で戻って来ない.
使用している所は次の様な感じ.
{ _MutexS_ mt(FALSE,_T("DocIB::GetBitmap")) ; MutexS m(&mt) ; { // 共有のリソースに対する操作 } }
通常の動作では Unlock されないことがある様には思えないが…
デバッガを使っていて Lock 中に exe を強制終了してしまったか?
_MutexS_ UseGdiPlus::ME(FALSE,_T("UseGdiPlus::GP_Token")) ; { MutexS me(&ME) ; if (IsInitialized()) { // ... } // .. }
いい修正方法が思い浮かばないので,とりあえずメモ.
2021/02/19
その後いろいろと検索して調べたが,通常の動作ではロックされたままとなることはなさそう.
https://docs.microsoft.com/ja-jp/dotnet/standard/threading/mutexes
表示されてはないが起動したままの exe があるかと思い,タスクバーを見たが特になさそう.
昨日,わかっているものの幾つかは「タスクの終了」で終わらせている.
そうなるとロックされている Mutex は,自前のシェルエクステンションと思われる.
「タスクバー」に表示されている「エクスプローラ」は終了させたが,まだ誰かがロックしている.
画面には表示されていない explorer.exe が幾つかか存在したので,すべて終わらせた.
これでロックされた Mutex は解放されたみたい.
今度は,デバッガを使用してうまく起動しなかった exe をいろいろ試すことに.
デバッガで Lock した直後にブレイクポイントを設定して停止.
当然であるが他の exe を起動すると Lock の所で止まってしまう.
デバッガで Unlock の後まで実行すると,他の exe も止まっていた所から動き出す.
デバッガで Lock した直後に停止させて,他の exe を起動.
デバッガで「デバッガの停止」してみる(Unlock していない)と,他の exe が動き出す.
これらの動作を見ると,使い方としてはそれ程間違ってはなさそう.
コードを追いかける限りでは,「マズい」所がわからない.
複数のプロセスから呼ばれた時に意図しないタイミングとなってしまう所があるのか?
ある程度はっきりしたのは,自前のシェルエクステンションの GDIPlus 関係の時の Lock で止まっていること.
SetConsoleCtrlHandler
コンソール AP で,キー入力による中断ができないかと…
やりたいことは,時間がかかるコンソール AP で,その途中までの計算結果を保存すること.
「コンソールアプリ 中断」で検索すると ::SetConsoleCtrlHandler を使えば良さそう.
MSDN を「PHANDLER_ROUTINE」で検索.次のサンプルが見つかった.
そのタイトル「Registering a Control Handler Function」で検索.
コントロール ハンドラー関数の登録
https://www.installsetupconfig.com/win32programming/
https://www.installsetupconfig.com/win32programming/winconsolecharapplication8index.html
T90Chi Windows Update その後
以前 Windows Update で,再起動を繰り返す状態になり そのままだった.
その後,幾つかの方法を試してみたが,BIOS 画面に入れずそのままとなっていた.
その時,音量の「-」と「電源ボタン」の同時長押しで起動すれば良い とあった.が,うまく入れないでいた.
久しぶりに調べてみると,USB キーボードを接続すれば良いとあったので試すとうまく BIOS 画面に入れた.
BIOS の起動は「F2」または「Delete」.「ESC」を押したときは「Please select boot device:」となる.
また,同じ様な状況になった人の記事も幾つかある.
ここまでは,昨日見つけた情報.
キーボード,マウス,Win10 インストール用 USB メモリ を接続して「ESC」を押して起動.
インストールを進めて…
上の「アップグレード」は選択してもその先に進めない.「カスタム」を選択.
4つのパーティションを削除.
「次へ」.
ライセンス認証は以前のものがそのまま引き継がれたみたい.
まだ設定は足りないが,何とか使えるようにはなった.
ドライブ名からリモート名に
ネットワークドライブ名から UNC での表現に変換するコード.
#include <clocale> #include "i_trace.hxx" //#include <winnetwk.h> #pragma comment (lib,"mpr.lib") tstring W_get_remote_name (LPCTSTR path_) { tstring dpath = path_ ; if (dpath.size() < 2) { return dpath ; } tstring drive = dpath.substr(0,2) ; tstring _path = dpath.substr(2) ; tstring remote_path ; if (drive.length() == 2) { if (drive[1] == _T(':')) { u_16 d_t = ::GetDriveType(drive.c_str()) ; if (d_t == DRIVE_REMOTE) { DWORD buf_size = MAX_PATH ; tstring remote_name ; remote_name.resize(buf_size+1) ; ::WNetGetConnection(drive.c_str(),&remote_name[0],&buf_size) ; if (!remote_name.empty()) { remote_path = remote_name.c_str() + _path ; } } } } if (remote_path.empty()) { return dpath ; } return remote_path ; } bool Test (void) { for (long index=0 ; index<26 ; index++) { tstring drv ; drv += TCHAR(_T('A')+index) ; drv += _T(":\\") ; // if (index%2 == 0) { u_16 d_t = ::GetDriveType(drv.c_str()) ; if (d_t == DRIVE_REMOTE) { drv += _T("*.*") ; v_tstring files = ::EnumFiles(drv.c_str()) ; if (files.size() > 0) { drv = files[0] ; } } } drv += _T(" ") ; tstring info = drv.substr(0,20) + _T("\t") + W_get_remote_name(drv.c_str()) ; { std::tout << info << std::endl ; } } return true ; } int _tmain (int argc,TCHAR* argv[]) { _tsetlocale(LC_ALL,_T("")) ; { ::Test() ; } return 0 ; }
「 net use 」とコマンド入力することで似た様なことを確認できる.
管理者で起動した PowerShell の Get-SmbConnection で SMB のバージョンを確認できる.
ファイル共有で使われている SMB のバージョンを見る
フォルダの更新日時の変更
今までファイルの更新日時の変更は使っていた.
https://www.vector.co.jp/soft/winnt/util/se500182.html
が,このツールでフォルダの更新日時を変更しようとするとできない.
コードは CFile::SetStatus を使用している.
CFileStatus fs ; CFile::GetStatus(file,fs) ; fs.m_mtime = newTime ; CFile::SetStatus(file,fs) ;
CFile::SetStatus の中(…\atlmfc\src\mfc\filest.cpp)を見ると ::SetFileTime を使用している.
また Linux などでも使える utime(…\crt\src\utime.c)も ::SetFileTime を使っている.
VC 6 で作成したものをデバッガで追いかけると ::CreateFile で 0xffffffff が返ってきている.
ASUSTOR NAS で試すと,特に問題なく変更できる.
Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ cat t_utime.cpp #include <clocale> #include "i_trace.hxx" #include "filetime.hxx" #include "itls_tmp.hxx" #include "c_which.hxx" int _tmain (int argc,TCHAR* argv[]) { _tsetlocale(LC_ALL,_T("")) ; { tstring temp_path = ::Get_i_Tools_tmp_date() ; tstring fold_path = ::Path_AddLastSP(temp_path) + ::Now_Format(_T("%H%M%S")) ; tstring file_path = ::Path_AddLastSP(temp_path) + ::Now_Format(_T("%H%M%S")) + _T(".tmp") ; { ::Folder_Create (fold_path) ; ::File_CreateEmpty(file_path) ; } { time_t f_time = ::File_GetMTime(file_path.c_str()) ; f_time-= 3600*24*7 ; ::File_SetMTime(file_path.c_str(),f_time) ; ::File_SetMTime(fold_path.c_str(),f_time) ; } { tstring cmd = tstring(cmd_ls_la) + _T(" ") + ::QuotM_Add_Auto(temp_path) ; _tsystem(cmd.c_str()) ; } } return 0 ; } Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ g++ t_utime.cpp -Wall Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ ll total 136 drwxrwxrwx 2 Iwao users 4.0K Nov 7 16:24 ./ drwxrwxrwx 3 Iwao users 4.0K Nov 7 15:32 ../ -rwxr-xr-x 1 Iwao users 122.7K Nov 7 16:24 a.out* -rwxrwxrwx 1 Iwao users 838 Nov 7 16:22 t_utime.cpp* Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $ ./a.out total 0 drwxr-xr-x 3 Iwao users 80 Nov 7 16:24 . drwxr-xr-x 3 Iwao users 60 Nov 7 16:24 .. drwxr-xr-x 2 Iwao users 40 Oct 31 16:24 162451 -rw------- 1 Iwao users 0 Oct 31 16:24 162451.tmp Iwao@AS5202T:/volume1/home/Iwao/gcc_test/Test/t_linux/t_mtime/t_utime $
2024/01/04
フォルダの更新日時の設定
Win10 他の PC が表示されない
::SHBrowseForFolder を使用している所で,最近 PC 名でアクセスできないと問合せが…
私自身はエクスプローラで直接入力していたので特に困ってはなかったが,ちょっと調べたのでメモ.
「Win10 他の PC が表示されない」で検索すると幾つかの対応方法が見つかる.
Windows10 – ネットワーク上のコンピューターが表示されない時の対処法
Windows 10 にてネットワークコンピュータが表示されない場合
【解決】ネットワークでコンピューターや共有フォルダが表示されない【Windows10】
Windows 10のエクスプローラの[ネットワーク]にPCが表示されない場合の対処方法
SMBv1 は、Windows 10 バージョン1709、Windows Server バージョン1709以降のバージョンでは既定でインストールされません。
「SMB 1」を入れる様な記述も多いが,「WS-Discovery」を利用する方法で…
動作を確認するために,タスクマネージャのサービスで「Function Discovery Resource Publication」を「開始」.
エクスプローラで見える様になる.
保有している NAS で,QNAP TS-253D は表示されている.
Synology NAS DS116 は「Windowsネットワーク探索を有効化して…」のチェックで表示されるようになる.
Synology NAS DS218jをWindowsからネットワーク探索
その他の NAS では設定がわからず,直接入力で対応.
実際はネットワークドライブとして割り当てたり,ショートカットを作成したりしている.
2021/11/10
Win10 などで,Windows Update してからアクセスできなくなった.
この場合は「ゲストログオンを有効にする」必要がある.
https://dev.mish.work/wordpress/2021/11/05/win-2022-classic-asp/
https://youtm-log.com/failure/pc-failure/anzendenai/
2024/12/05
サーバの共有フォルダにアクセスできなくなった場合は,共有アクセス用のアカウントを追加する.
https://dev.mish.work/wordpress/2024/11/15/add-user-win11-24h2/
サーバ上のフォルダ名を記憶可能なツールを追加.
https://download.mish.work/iTls_2024_11.zip
コンソール AP での define
コンソール AP で Windows.h や Afx.h を読み込んだ時のエラーに対応するために i_def_aw.hxx を用意.
_AFXDLL で判断しているため「MFC のスタティックライブラリを使用」には対応できない.
// (VS8)\VC\AtlMFC\Include\AfxV_W32.h #ifdef _MSC_VER #ifdef _UNICODE #ifndef UNICODE #define UNICODE // UNICODE is used by Windows headers #endif #endif #ifdef UNICODE #ifndef _UNICODE #define _UNICODE // _UNICODE is used by C-runtime/MFC headers #endif #endif #endif #ifdef _MSC_VER #ifdef _AFXDLL #include <Afx.h> #else #include <Windows.h> #endif #endif #ifdef _MFC_VER // ... #endif
2022/07/27
その後,Windows.h を使用するコードを書いていてのまとめ.
#include "i_def_aw.hxx" // #include <Windows.h>
Win32 API のみで書いていて,MFC を利用する可能性がある場合は,この様に置き換え可能と思われる.
そうでない場合は,それらを利用するソースの先頭で Afx.h または i_def_aw.hxx をインクルードすれば良い.
https://dev.mish.work/wordpress/?s=i_def_aw
2022/08/01
今回書いた FVersion.hxx の様に MFC を利用しないものは,Windows.h の方が良い.
MFC コードが混在する場合 は,i_def_aw.hxx の利用と _MFC_VER での振り分けが良さそう.
robocopy でエラー 50 (0x00000032)
次の様なコマンドでファイルをバックアップしていると,
robocopy "\\DevX\Public\Documents\Develop" "\\AS5202T\Public\Document\Develop" /e /xo /xf *.bak ... 6 \\DevX\Public\Documents\Develop\VC_Test\T_mem\T_PhysF\ 8 \\DevX\Public\Documents\Develop\VC_Test\T_STL\ 2020/09/11 10:03:08 エラー 50 (0x00000032) コピー先ディレクトリにアクセスしています \\AS5202T\Public\Document\Develop\VC_Test\T_STL\ この要求はサポートされていません。 30 秒間待機しています... 再試行しています...
何かの拍子に開いたままの状態になってしまったみたいで ASUSTOR NAS で「切断」することで対応.
* 使用しているユーザを切断しない様に注意.