スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
 

検索機能(X-Finder/Tablacus Explorer)

今回、X-FinderとTablacus Explorerに検索機能を追加しました。
FilterViewってフィルタだと思い込んでいたのですが、ひょんなことから試してみたら、検索だったので、びっくりしました。

この検索はWindows Vista以降しか対応していませんが、Advanced Query Syntax(AQS)に対応していて、例えば、「更新日時:今週」を検索すると今週の項目が検索され、「更新日時:>2014/2/1」とすれば2014年2月1日以降の項目が検索されます。

「更新日時:今週 AND 拡張子:exe」等の複数の項目を検索することもできます。

また、スクリプトを使えば、10日前から今日までの項目を検索する場合はX-Finderでは以下のランチャを実行すればOkです。

Script:JScript
WScript.Exec('Search:更新日時:>' + new Date(new Date() - 86400000 * 10).toLocaleString());


Tablacus Explorerではタイプを「JScript」にしてパスを以下のようにします。

var FV = te.Ctrl(CTRL_FV);
if (FV) {
  FV.FilterView('更新日時:>' + new Date(new Date() - 86400000 * 10).toLocaleString());
}


* 10 の10を変えると何日前からかを変更できます。
 
スポンサーサイト

続・カスペルスキーの問題

カスペルスキーに調査用データを送って調べてもらったのですが、動作の遅延やエラーなどの発生もなく正常とのこと。
こちらでは問題が出るので今度は簡単なテストプログラムと結果とトレースログを送ってみました。
あちらでも問題が出ればバグをサクッと発見できるのでしょうが、発生しない不具合の発見は難しいですから…
カスペルスキーを使っていて右クリックが遅くなる方はカスペルスキーに連絡お願いします。やっぱり、情報が多いほうが対策しやすいと思います。

今回、送ったのは以下のようなプログラムのexeとVC++ 2008のソース

テストした環境ではシステムウォッチャーoff時は120 msですが、onにすると13720 ms掛かってしまいました。さすがに13秒は長すぎる…

もし、テストプログラムが欲しい方が居られましたら連絡ください。

::CoInitialize(NULL);
WCHAR szFile[MAX_PATH];
WCHAR szTime[MAX_PATH];
LPWSTR pszExt;
GetModuleFileName(NULL, (LPWSTR)szFile, MAX_PATH);
pszExt = PathFindExtension(szFile);
lstrcpy(pszExt, L".txt");
HANDLE hFile = CreateFile(szFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(hFile);
LPITEMIDLIST pidlFull = ::ILCreateFromPath(szFile);
IShellFolder *pSF = NULL;
LPCITEMIDLIST pidlChild = NULL;
SHBindToParent(pidlFull, IID_PPV_ARGS(&pSF), &pidlChild);
IContextMenu *pCM = NULL;
pSF->GetUIObjectOf(NULL, 1, &pidlChild, IID_IContextMenu, NULL, (LPVOID*)&pCM);
HMENU hMenu = CreatePopupMenu();
DWORD dwStart = GetTickCount();
pCM->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_DEFAULTONLY);
DWORD dwEnd = GetTickCount();
DestroyMenu(hMenu);
pCM->Release();
pSF->Release();
::CoTaskMemFree(pidlFull);
::OleUninitialize();
swprintf_s(szTime, MAX_PATH, L"%d ms", dwEnd - dwStart);
MessageBox(NULL, szFile, szTime, MB_ICONINFORMATION | MB_OK);


※このプログラムでは赤の部分に掛かる時間を調べて表示します。 

フォルダの監視(Tablacus Explorer)

Tablacus Explorer 14.2.10からシェル関数のSHChangeNotifyRegister関数でフォルダを監視するようにしました。

フォルダ内の更新はエクスプローラ互換のコントロールを使っている関係で自動的にやってくれるので、今回は開いているタブのフォルダ自体が削除されたり、名前が変更された場合に対応できる様に対策しました。

SHChangeNotifyRegisterでデスクトップを指定してfRecursiveをTRUEにすれば、すべてのフォルダやファイルを削除やリネーム等の通知対象にできます。

ただ、更新日時の変更等の細かい通知はこれでは取得できず、その親フォルダをSHChangeNotifyRegisterで指定する必要があります。

また、SHChangeNotifyRegister関数では気を付けなければいけない事があります。
それは、SHCNE_RENAMEITEMやSHCNE_RENAMEFOLDERで取得する名前の変更後のITEMIDLISTが壊れているようでそのままでは使えない事です。
一度、文字列に直してITEMIDLISTに戻すと上手くいきます。
そして、SHChangeNotifyRegisterで指定したフォルダはロックされます。ディスクの取り出しを選んだ時の通知を取る方法があれば良いのだけれど……
 

ZIPフォルダ内をIShellFolder2で列挙してみた。

前回はIStorageでの列挙でしたが、今回はIShellFolder2→IEnumIDListで列挙できるか試してみました。
IStreamの取得もIShellFolder2->BindToStorageでできました。

ItemIDListからファイル名に変換する場合はIStorageでの列挙の方が簡単ですね。
そして、IShellFolderとIStorageって両方使える場合が多そうな感じがします。
ファイル名や更新日時しか取得しないのであれば、普通のフォルダもIShellFolderの代わりにIStorageで列挙したほうが簡単かも。

IStorage版はTablacus ExploerのソースのteExtractをご覧ください。

HRESULT teExtract2(IShellFolder2 *pSF2, LPWSTR lpszFolderPath)
{
  LPITEMIDLIST pidl;
  IEnumIDList *pEnumIDList;
  ULONG celtFetched;
  STRRET strret;
  ULONG dwAttributes;
  FILETIME mtime;
  SYSTEMTIME SysTime;
  SHCOLUMNID scid;
  scid.fmtid = FMTID_Storage;
  scid.pid = 14;
  VARIANT v;

  CreateDirectory(lpszFolderPath, NULL);

  HRESULT hr = pSF2->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList);
  if FAILED(hr) {
    return hr;
  }
  while (pEnumIDList->Next(1, &pidl, &celtFetched) == S_OK) {
    if SUCCEEDED(pSF2->GetDisplayNameOf(pidl, SHGDN_NORMAL, &strret)) {
      BSTR bs;
      if SUCCEEDED(StrRetToBSTR(&strret, pidl, &bs)) {
        WCHAR *lpszPath = new WCHAR[lstrlen(lpszFolderPath) + ::SysStringLen(bs) + 2];
        PathCombine(lpszPath, lpszFolderPath, bs);
        dwAttributes = SFGAO_FOLDER;
        pSF2->GetAttributesOf(1, const_cast(&pidl), &dwAttributes);
        if (dwAttributes & SFGAO_FOLDER) {
          IShellFolder2 *pSF2New;
          pSF2->BindToObject(pidl, NULL, IID_PPV_ARGS(&pSF2New));
          teExtract2(pSF2New, lpszPath);
          pSF2New->Release();
        }
        else {
          IStream *pStream;
          ULONG uRead;
          DWORD dwWriteByte;

          hr = pSF2->BindToStorage(pidl, NULL, IID_PPV_ARGS(&pStream));
          if SUCCEEDED(hr) {
            LPBYTE lpData = (LPBYTE)CoTaskMemAlloc(SIZE_BUFF);  
            if (lpData) {
              HANDLE hFile = CreateFile(lpszPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
              if (hFile) {
                while (SUCCEEDED(pStream->Read(lpData, SIZE_BUFF, &uRead)) && uRead) {
                  WriteFile(hFile, lpData, uRead, &dwWriteByte, NULL);
                }
                VariantInit(&v);
                if SUCCEEDED(pSF2->GetDetailsEx(pidl, &scid, &v) && v.vt == VT_DATE) {
                  if (::VariantTimeToSystemTime(v.date, &SysTime)) {
                    ::SystemTimeToFileTime(&SysTime, &mtime);
                  }
                }
                VariantClear(&v);
                SetFileTime(hFile, NULL, NULL, &mtime);
                CloseHandle(hFile);
                hr = S_OK;
              }
              else {
                hr = E_ACCESSDENIED;
              }
              teCoTaskMemFree(lpData);
            }
            else {
              hr = E_OUTOFMEMORY;
            }
            pStream->Release();
          }
        }
        ::SysFreeString(bs);
        delete [] lpszPath;
      }
    }
    teCoTaskMemFree(pidl);
  }
  pEnumIDList->Release();
  return hr;
}

 

ZIPフォルダ機能無効化でも解凍する(Tablacus Explorer)

Tablacus Explorer 14.1.27からはZIPフォルダ機能が無効化されている場合はzipfldr.dllを直接使ってZIPを解凍する機能を追加しました。
Windowsの高速化などでZIPフォルダ機能を無効化している場合には、アドオンの解凍で解凍ソフトを指定する必要があったのですが、これで指定無しでもアドオンのインストールやTablacus Explorerのアップグレードができるようになりました。

ZIPフォルダ機能無効化でCoCreateInstanceが失敗する場合はLoadLibraryでモジュールをロードしてDllGetClassObjectとIClassFactory->CreateInstanceでインスタンスを作成します。(teCreateInstance)
このインスタンスからはIPersistFile、IStorage、IShellFolder2等が取得できます。
そして、IPersistFile->Loadでファイルを指定し、IStorageを使って解凍します。(teExtract)
XPの場合はIEnumSTATSTGで更新日時を取得できないようなので、IShellFolder2->GetDetailsExで更新日時を取得しています。

IStorageからIEnumSTATSTGでZIPの一覧を取得していますが、IShellFolderからIEnumIDListでZIPの一覧を取得する方法も使えそうな気がします。XPの更新日時を考えるとこっちも良いかな。

詳しくはTablacus Exploerのソースをご覧ください。
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。