「ほっ」と。キャンペーン
<   2014年 02月 ( 16 )   > この月の画像一覧
(.Net)フォルダ削除のDirectory.Delete(path, true)にやられた

.Netの System.IO.Directory.Delete(path, true) を使ってサブフォルダ・ファイルごと任意のディレクトリを削除しようとしたのですが、"アクセスが拒否されました" とIOException例外になります。


??ってなってたら、サブフォルダの一つが読み取り専用属性がついていました。
Directory.Deleteで削除しようとする場合、読み取り専用属性がついてると削除させてくれないようです。

対処法としては、一旦サブフォルダの読み取り専用属性を全てのけてから、Directory.Deleteメソッドを実行するしかなさそうですorz...
(VB.NET用のMy.Computer.FileSystem.DeleteDirectoryメソッドを使うと一気に消せるようですが。。)

読み取り専用ファイルがあるときでもフォルダを削除する: DOBON.NET Tips: C#, VB.NETに、一旦読み取り専用属性のけてから削除するサンプルコードがあるので、これを使わせてもらいました。

今まで.Netそこそこは触ってきたはずなのに、未だにこんな仕様で驚いている3流PGでした。。。
[PR]
by jehoshaphat | 2014-02-15 01:06 | .Net開発 | Trackback | Comments(0)
(バッチ)メッセージボックスを表示したい
バッチファイル実行時に、ユーザに重要な情報を伝えたい時に、コマンドプロンプト画面内での表示ではインパクトが薄いのでメッセージボックスで表示したいと思いました。

以下のようにすれば、それが可能なようです。
echo "テストです" | msg 0

/w をつけると、OKボタンを押さないと次の処理に進まなくできるようです。
echo "OKボタンを押してください" | msg 0 /w


参考:
MSGコマンドを使ってコマンドプロンプトやバッチファイルからメッセージボックスを出す。
batファイルでメッセージを出す方法 これは一旦VBSファイルにリダイレクトする方法を使ってます
[PR]
by jehoshaphat | 2014-02-14 01:05 | VBScirpt,WSH,バッチ | Trackback | Comments(0)
(バッチ)32bitか64bitか判断する
バッチファイルで、今バッチを実行しているOSがx86(32bit)なのかx64(64bit)なのか判断したいと思いました。
で、ググると、バッチファイルで64ビットと32ビット違うコマンドを実行するにドンピシャな情報が。。

コピペですが、以下のバッチで判断できるようです。


@echo off
if "%PROCESSOR_ARCHITECTURE%" EQU "x86" (
echo "x86"
)
if "%PROCESSOR_ARCHITECTURE%" NEQ "x86" (
echo "x64"
)
pause

[PR]
by jehoshaphat | 2014-02-14 01:00 | VBScirpt,WSH,バッチ | Trackback | Comments(1)
VNXeのCIFS共有フォルダでフォルダ・ファイル操作ログを取る方法
EMCのエントリーストレージ VNXe3100 で、CIFS共有フォルダを使ってるんですが、ファイル操作ログを取る必要が出てきました。

Unishphereを見てもファイル操作ログを取るような設定がありません。
で、サポートの方に聞いてみたら、「CIFS共有フォルダでのEMC VNXeシステムの使用」ドキュメントの「Windows ツールによるVNXe CIFS共有フォルダストレージの管理」のページに説明があるとのことでした。


マニュアルは、VNXeサポートページにログインし、製品ごとのサポート→VNXe Series→ドキュメントからダウンロードできます。

マニュアルと見ると、Windowsの監査ログの機能を使って、ファイル操作ログが取れるようです。

通常のファイルアクセス監査ログを取る場合も、GPOかローカルグループポリシーエディタで監査機能を有効にする必要がありますが、VNXeも同様です。
今回は、GPOを使わずに設定することにしました。

その場合、Celerra DataMover セキュリティ設定スナップイン という拡張ソフト(拡張スナップイン)を入れる必要があるようです。

このソフトを探すのに苦労しました。
結局、ダウンロード→適当に製品選び→右側の 製品/サポート・ツール →検索窓に "cifs" で検索→ VNX File/CelerraCifsMgmt.exe をダウンロードできました。

32bit用なので、x86のWindowsにドメイン管理者権限で、インストールしてやる必要があります。


インストール後、mmc.exeを起動し、[ファイル]→[スナップインの追加と削除]→[追加]→[Data Mover Management]でスナップインを追加します。
コンソールルートに Data Mover Management が追加されているので、右クリック→[Connect to Data Mover...]で設定を行うVNXe上の共有フォルダサーバを指定します。


まずは、監査機能を有効にしてやる必要がるので、Data Mover Managementスナップインの、[Data Mover Security Setting]→[Audit Policy]を右クリックし、[Enabled auditing]にして、有効にします。(逆に無効にする場合は、[Disable auditing]にします)
後は、[Audit Policy]配下にあるどの監査を行うか設定します。
このあたりは、通常のグループポリシーで監査を行う場合と同じですね。英語なんでちょっとわかりにくいですが。。。
今回はファイルアクセス監査ログをとりたいので、[Audit object access]ポリシーで成功時、失敗時とも監査するようにしました。


後は、どのフォルダ・ファイルに対して監査するか設定します。
このあたりも通常のWindowsファイルサーバと同じで、フォルダのプロパティのセキュリティから、どのユーザで、どのアクションをした時にログに残すか設定します。
ただ、ファイル・フォルダ数が多いフォルダで、監査の設定をすると、反映するのに相当時間がかかりました。

監査ログは、コンピュータの管理スナップインを立ち上げ、VNXe上の共有フォルダサーバに接続し、セキュリティイベントログから確認できます。
イベントログのサイズ等も、通常のWindowsと同じようにセキュリティイベントログを選択し、プロパティから変更できます。

このイベントログの実体ファイル(security.evt)は、\\共有フォルダサーバ名\c$ 直下にあるようです。
実は,c$配下にはスナップショットデータもあったり,コンピュータの管理から、ログイン中のユーザや使用中のファイルがわかったりといろいろ面白い発見があります。

VNXeサービス情報を取得して中を見てると、Linuxを使っているようですが、このあたりのWindowsとの親和性が高いのも、安物のLinuxNASとは大違いですね。

参考:
ドメインコントローラでオブジェクトアクセス監査を有効にすると。。。
マイクロソフト サーバー製品の ログ監査ガイド 監査ログについてわかりやすく説明されています。
[PR]
by jehoshaphat | 2014-02-13 00:57 | サーバがらみ | Trackback | Comments(0)
(.Net)任意のプロセスのCPU使用率を出すコード
任意のプロセスのCPU使用率を求めたいと思ってググっていたらVisualStudioフォーラム:複数のプロセス毎のCPU使用率同時取得にドンピシャな答えがありました。

コピペになりますが、ベンチマークソフト SUPER_PI のCPU使用率を求めたい時はこうなります。
mSystemProcessNameで、プロセスイメージ名(拡張子は無し)を指定します。

このPGでは指定したプロセスのCPU使用率しか求めれないため、全プロセスのCPU使用率を知りたい時は、一旦全プロセスイメージ名を取得して、それぞれ別スレッドでこのコードを動かすみたいな作りになろうかと思います。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
 
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
bool mStop = false;
string mSystemProcessName = "SUPER_PI";
int mMonitorInterval = 1;
 
/// <summary>パフォーマンスカウンタ・カテゴリ名(プロセス)</summary>
const string CATEGORY_NAME = "Process";
/// <summary>パフォーマンスカウンタ・カテゴリ名(プロセッサ)</summary>
const string CATEGORY_NAME_PROCESSOR = "Processor";
/// <summary>パフォーマンスカウンタ・カウンタ名(プロセッサ使用時間)</summary>
const string COUNTER_NAME_PROCESSOR_TIME = "% Processor Time";
/// <summary>ナノ秒単位での1秒の値</summary>
double NANO_SECOND_TICKS = 10000000;
/// <summary>CPUのコア数</summary>
double mCoreNumber;
 
#region 指定時間間隔内でのデータ格納領域
/// <summary>プロセッサ使用時間</summary>
double[] mDataContainer_ProcessorPercent= new double[10];
#endregion
 
#region 直前の監視タイミングでのデータ格納領域
/// <summary>プロセッサ使用時間</summary>
double mBefor_ProcesserPercent=0;
#endregion
 
PerformanceCounter mProcessTime;
 
#region CPUのコア数取得
PerformanceCounter mWorkCounter_CoreNumber;
 
mCoreNumber = 1;
if (PerformanceCounterCategory.Exists(CATEGORY_NAME_PROCESSOR))
{
if (PerformanceCounterCategory.CounterExists(COUNTER_NAME_PROCESSOR_TIME, CATEGORY_NAME_PROCESSOR))
{
for (int i = 0; i < 32; i++)
{
try
{
string wkInst = i.ToString();
mWorkCounter_CoreNumber = new PerformanceCounter(CATEGORY_NAME_PROCESSOR, COUNTER_NAME_PROCESSOR_TIME, wkInst, ".");
long buf = mWorkCounter_CoreNumber.RawValue;
mCoreNumber = double.Parse((i + 1).ToString());
}
catch
{
break;
}
}
}
}
#endregion
 
#region プロセスのパフォーマンスカウンタ定義
 
 
// プロセッサ使用時間
mProcessTime = new PerformanceCounter(
CATEGORY_NAME,
COUNTER_NAME_PROCESSOR_TIME,
mSystemProcessName,
".");
#endregion
 
// カレント時間を取得
DateTime current = DateTime.Now;
// ループ
while (true)
{
// ストップフラグが設定されたらループエンド
if (mStop) break;
// カレント時間の秒とが現在の秒と異なるか?
if (DateTime.Now.Second != current.Second)
{
// カレント時間の更新
current = DateTime.Now;
// カレント秒をログ出力間隔で割る
int div_sec = current.Second % mMonitorInterval;
// カレント秒がログ出力間隔で割り切れるか?
if (div_sec == 0)
{
//------------------------------------------------
// 監視間隔が切り替わるタイミングでログ情報出力
//------------------------------------------------
//PutLog(current); // ログファイルへデータ登録
//InitWorkArea(); // データ格納クラスの初期化
}
// CPU使用率 CPU使用時間(単位:100ナノ秒) / 1秒(10000000*100ナノ秒)/ CPUのコア数
mDataContainer_ProcessorPercent[div_sec] = (mProcessTime.RawValue - mBefor_ProcesserPercent) / NANO_SECOND_TICKS / mCoreNumber;
//CPU使用率出力
Debug.WriteLine(mDataContainer_ProcessorPercent[div_sec]);
// 直前の値として退避
mBefor_ProcesserPercent = mProcessTime.RawValue;
}
Thread.Sleep(10);
}
}
}
}


参考:
プロセス毎のCPU使用率の取得: DOBON.NETプログラミング掲示板過去ログ
CPU使用率(C#/VB.NET) [サンプルソース] [ヨーキー景吾の逃走]
C++でCPU使用率やメモリ使用量を調べる - 小さな星がほらひとつ C++の場合はこの方法でプロセスのCPU使用率も取れるようです。
[PR]
by jehoshaphat | 2014-02-12 00:53 | .Net開発 | Trackback | Comments(0)
(.Net)ターミナルサーバでユーザのプロセスのメモリ使用量を取りたい。
WindowsServer2003上でターミナルサーバを運用してますが、どうやらメモリを使いすぎているユーザがいるようです。
それで、数日間どのユーザがどのプロセスでメモリを使いすぎているのか経過調査を行うことにしました。


当初はパフォーマンスログで取ろうかなと思っていたんですが、パフォーマンスログではそのプロセスを使っているのがどのユーザなのかがわかりません。

仕方が無いので .Net Framework で現在のプロセス情報を取得し、ユーザと紐付けてCSVに落とすアプリケーションを作ることにしました。
それをOSのタスクスケジューラーに仕込んで、一定間隔で動かす運用です。

CSVには全プロセスの情報と、ユーザ単位でメモリ使用量を集計した情報を別々に出力します。

現在動いているプロセスの情報は System.Diagnostics.Process.GetProcesses() で取れるんですが、そのプロセスがどのユーザがオーナーとなっているかがわかりません。
ココは(.Net)現在のユーザが起動した特定のプロセスを終了するで書いた WMI を使った方法を取ることにしました。


コードしては以下のような感じです。文字数制限のためハイライトはOFFです。(C# .NetFramework2.0)

try{
//ユーザとプロセスIDを取得。(WMI使用)
ManagementScope scope = new ManagementScope("\\\\.\\ROOT\\CIMV2");

//プロセス情報取得
System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcesses();

scope.Connect();
ObjectQuery query = new ObjectQuery(@"SELECT * FROM Win32_Process");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection col = searcher.Get();

//プロセスIDとユーザ名のハッシュテーブル[プロセスID,ユーザ名]
Hashtable htPrcUsrMap = new Hashtable();
foreach (ManagementObject o in col){
string pid = o["ProcessId"].ToString();

Object[] UserInfo = new object[2];
//見つからない時があるので、try - catch
try{
o.InvokeMethod("GetOwner", UserInfo);
}catch (Exception){
UserInfo[0] = "unkwon";
}

string UserName = (string)UserInfo[0]; //実行ユーザ名称取得
//string DomainName = (string)UserInfo[1]; //実行ユーザのドメイン名称取得

//配列にプロセスIDとユーザ名格納
htPrcUsrMap.Add(pid, UserName);
}

//現在日時取得
DateTime dt = DateTime.Now;
//データを格納するためのテーブルインスタンス作成
DataSet1.tblProcessDataDataTable tbl = new DataSet1.tblProcessDataDataTable();

//出力ファイル名
string strExportFile_Process = @"C:\PerfLogs\processCounter_Process.csv";
string strExportFile_User = @"C:\PerfLogs\processCounter_User.csv";

StringBuilder strBld_Process = new StringBuilder();

foreach (System.Diagnostics.Process p in ps){
try{
DataSet1.tblProcessDataRow row = tbl.NewtblProcessDataRow();

//タイムスタンプ出力(日時分)
string timestamp = dt.ToString("yyyy-MM-dd HH:mm:00");
strBld_Process.Append(timestamp);
strBld_Process.Append(",");
row.timestamp = timestamp;

//ユーザ名出力
string user = (string)htPrcUsrMap[p.Id.ToString()];
strBld_Process.Append(user);
strBld_Process.Append(",");
row.user = user;

//プロセスID
string processId = p.Id.ToString();
strBld_Process.Append(processId);
strBld_Process.Append(",");
row.process_id = processId;

//プロセス名
string processName = p.ProcessName;
strBld_Process.Append(processName);
strBld_Process.Append(",");
row.process_name = processName;

//CPU使用率(未実装。とりあえず0にしておく)
double cpuPercent = 0;
strBld_Process.Append(cpuPercent);
strBld_Process.Append(",");
row.cpu = cpuPercent;

//CPU時間
TimeSpan cpuTime = p.TotalProcessorTime;
strBld_Process.Append(cpuTime.TotalSeconds);
strBld_Process.Append(",");
row.cpu_time = (decimal)cpuTime.TotalSeconds;

//workingset(物理メモリ使用量)
long workingset = p.WorkingSet64;
strBld_Process.Append(workingset);
strBld_Process.Append(",");
row.workingset = workingset;

//PrivateMemory(物理メモリ+スワップ使用量)
long privateMemory = p.PrivateMemorySize64;
strBld_Process.Append(privateMemory);
strBld_Process.Append(",");
row.privatememorysize = privateMemory;

//最大workingset
long perkworkingset = p.PeakWorkingSet64;
strBld_Process.Append(perkworkingset);
strBld_Process.Append(",");
row.peak_workingset = perkworkingset;

//プロセスパス
string processPath = p.MainModule.FileName;
strBld_Process.Append(processPath);
strBld_Process.Append(",");
row.process_path = processPath;

/*
//メインウィンドウキャプション(実行ユーザでしか出ない)
string windowCaption = p.MainWindowTitle;
strBld_Process.Append(windowCaption);
strBld_Process.Append(",");
*/

strBld_Process.Append(Environment.NewLine);
tbl.AddtblProcessDataRow(row);
}catch (Exception ex){
Console.WriteLine("エラー: {0}", ex.Message);
strBld_Process.Append(Environment.NewLine);
}
}

//ユーザ毎の統計データ生成
//重複を除去するため DataView を使う
DataView vw = new DataView(tbl);
//重複除去を第二引数に指定。第三引数で一意とすべき列を指定。(複数列でも可能)
DataTable tblRes = vw.ToTable("DistinctTable", true, new string[] { "user" });
//合計の列を追加
tblRes.Columns.Add("sum_cpu", Type.GetType("System.Double"));
tblRes.Columns.Add("sum_workingset", Type.GetType("System.Int64"));
tblRes.Columns.Add("sum_privatememorysize", Type.GetType("System.Int64"));
tblRes.Columns.Add("sum_processcount", Type.GetType("System.Int64"));
tblRes.Columns.Add("sum_cputime", Type.GetType("System.Decimal"));

//重複除いたDataTableをループし、元のDataTableから集計値を求める
foreach (DataRow row in tblRes.Rows) {
row["sum_cpu"] = tbl.Compute("SUM(cpu)", "user = '" + row["user"] + "'");
row["sum_cputime"] = tbl.Compute("SUM(cpu_time)", "user = '" + row["user"] + "'");
row["sum_workingset"] = tbl.Compute("SUM(workingset)", "user = '" + row["user"] + "'");
row["sum_privatememorysize"] = tbl.Compute("SUM(privatememorysize)", "user = '" + row["user"] + "'");
row["sum_processcount"] = tbl.Compute("Count(user)", "user = '" + row["user"] + "'");
}

//sum_workingset の降順でソートをかける
DataRow[] srtRows = (DataRow[])tblRes.Select("" , "sum_workingset DESC").Clone();
DataTable tblSrt = new DataTable();
tblSrt = tblRes.Clone();
foreach (DataRow row in srtRows){
tblSrt.ImportRow(row);
}

//テキスト生成
StringBuilder strBld_User = new StringBuilder();
strBld_User = new StringBuilder();
foreach (DataRow row in tblSrt.Rows){
strBld_User.Append(dt.ToString("yyyy-MM-dd HH:mm:00"));
strBld_User.Append(",");
strBld_User.Append(row["user"]);
strBld_User.Append(",");
strBld_User.Append(row["sum_cpu"]);
strBld_User.Append(",");
strBld_User.Append(row["sum_cputime"]);
strBld_User.Append(",");
strBld_User.Append(row["sum_workingset"]);
strBld_User.Append(",");
strBld_User.Append(row["sum_privatememorysize"]);
strBld_User.Append(",");
strBld_User.Append(row["sum_processcount"]);
strBld_User.Append(",");
strBld_User.Append(Environment.NewLine);
}

//ファイル出力
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
if (!File.Exists(strExportFile_Process)){
string strHead = "日時,ユーザ,プロセスID,プロセス名,CPU使用率(未実装)"
+ ",CPU時間,物理メモリ使用量,物理+スワップ使用量,最大物理メモリ使用量,プロセスパス";//,ウィンドウ名";
File.AppendAllText(strExportFile_Process, strHead + Environment.NewLine, enc);
}
if (!File.Exists(strExportFile_User)){
string strHead = "日時,ユーザ,CPU使用率合計(未実装)"
+ ",CPU時間合計(秒),物理メモリ使用量合計,物理+スワップ使用量合計,プロセス数";
File.AppendAllText(strExportFile_User, strHead + Environment.NewLine, enc);
}
File.AppendAllText(strExportFile_Process, strBld_Process.ToString(), enc);
File.AppendAllText(strExportFile_User, strBld_User.ToString(), enc);

}catch (Exception ex){
File.AppendAllText(@"C:\PerfLogs\err.txt" , DateTime.Now.ToString() + " " + ex.Message + " Trace:" + ex.StackTrace + Environment.NewLine);

}



ユーザの統計に使う DataTable は以下のような構成にしてます。

データセット名:DataSet
テーブル名:tblProcessData
列:timestamp :System.String
列:user :System.String
列:process_id :System.String
列:process_name :System.String
列:cpu :System.Double
列:workingset :System.Int64
列:privatememorysize :System.Int64
列:peak_workingset :System.Int64
列:process_path :System.String
列:cpu_time :System.Decimal

実際に動かすと、WMIを使ってプロセスとユーザ情報を取得する部分が非常に時間がかかります。
60ユーザくらいで800-900くらいのプロセスが動いている状態で、数分はかかります。
また、この部分、CPUも結構食うようで1コア専有しちゃうんですよね。

WMI以外にユーザとプロセスの情報を取る方法が知りたいと思う今日この頃です。

参考:
MSDN:Process メンバ (System.Diagnostics)
[VB / C#] 実行中プロセスの各種情報を取得
【C#】プロセス実行ユーザ名称の取得API - Insider.NET - @IT
[PR]
by jehoshaphat | 2014-02-11 00:46 | .Net開発 | Trackback | Comments(0)
(OpenOffice)Calcでセルの中をコピーしようとするとフリーズする
Windows7環境の OpenOffice3.3 で、Calc使ってるんですが、あるCalcファイルでセルの中の文字列に対しコンテキストメニューを表示してコピー等の操作を使用とすると、以下のようにOpenOfficeが落ちてしまいます。
(他のファイルはなりません)
e0091163_0454144.jpg


エラーの内容を見ると、以下のようになっていました。

問題の署名:
問題イベント名:BEX
アプリケーション名:soffice.bin
アプリケーションのバージョン:3.3.9556.500
アプリケーションのタイムスタンプ:4d061efd
障害モジュールの名前:spellmi.dll
障害モジュールのバージョン:3.3.9556.500
障害モジュールのタイムスタンプ:4f21f2e5
例外オフセット:0001b673
例外コード:c0000409
例外データ:00000000
OS バージョン:6.1.7601.2.1.0.256.48
ロケール ID:1041
追加情報 1:33df
追加情報 2:33df374cff7c82f5a73bc853d1d76b28
追加情報 3:0ac8
追加情報 4:0ac86277dbf5578e8739d3cec49def4e


どうやら、スペルチェックのDLLがクラッシュしているようです。
確かに、セルの中は日本語文字列なんですが、ほとんどの単語でスペルミスを表す赤線が表示されています。

色々調べたとことろ、セルの書式設定→フォント→アジア諸言語用フォント→言語 の値が 空白 でした。
e0091163_0454627.jpg


ここは普通、空白になっていてはいけない項目です。
どうやらファイルが壊れて、空白になっていたようです。
ここを日本語に設定することでスペルミスはなくなり、エラーは発生しなくなりました。
[PR]
by jehoshaphat | 2014-02-10 00:40 | OpenOffice | Trackback | Comments(0)
(正規表現)任意の文字が含まれる行を削除する方法
ログファイル等で、任意の文字を含まない行を抽出する必要があります。
例えば、「正常」が入っている行は削除し、それ以外の行を知りたい場合です。

その場合、正規表現を使った検索/置換ができるテキストエディタがあれば容易に抽出ができます。

検索に以下のように指定し、置換文字列をなしにすればOKです。

^.*正常.*\n


参考:
正規表現サンプル(ある文字が含まれる行を削除する)
[PR]
by jehoshaphat | 2014-02-09 00:39 | 豆知識 | Trackback | Comments(0)
UltraVNCをWindows7に入れたらCtrl+Alt+Delが効かない
UltraVNC 1.0.9.6.1 を Windows7 の端末に入れてサービスモードで動かしているんですが、リモートしたときに Ctrl+Alt+Del ボタンが効きません。
再起動後ログオンする時などに相当不便です。

スクリーンキーボード等も試して見ましたがダメでした。

いろいろ調査した結果、グループポリシーの設定変更で対応できることがわかりました。

設定するのは、以下のグループポリシーです。

「コンピュータの構成」→「管理用テンプレート」→「Windowsコンポーネント」→「Windowsログオンオプション」→「ソフトウェアのSecure Attention Sequenceを無効または有効にする」を開き「有効」を選択。さらに「Secure Attention Sequenceの生成が許可されるソフトウェアの設定」で一覧より「サービス」を選択。


どうやらVista以降セキュリティ強化の一環で、ログオン処理が見直されたようです。
上記のグループポリシーを有効にすることで、ログオン処理などを行なうロック画面を描画する「Winlogonデスクトップ」から、通常処理を行なうアプリケーションデスクトップへ移行する際に呼び出す処理であるSAS(Secure Attention Sequence)を、ソフトウェアから行うことができるようになる仕掛けのようですね。

Windowsのログオン処理ちょっと調べたら結構興味深いです。
XP以前はWinlogonを拡張するためのGINA(Graphical Identification aNd Authentication)という機能があって、ここでもいろいろできてたようです。
詳しくは参考リンク参照。。。


参考:
仕事のカタマリ
UltraVNCの小技(4) cad.exe の導入 | Memo About Keisanki
Windows NTのログオンダイアログボックスをカスタマイズする方法
【コラム】Windows XPスマートチューニング (227) パスワードにまつわる設定を行なう | パソコン | マイナビニュース
スマートカードを使ったVistaのセキュリティ強化(1/2) - インターネットコム
[PR]
by jehoshaphat | 2014-02-08 00:38 | ツール | Trackback | Comments(0)
OfficePersonal2003とAccess2000混在時にエラー1706がでる

OfficePersonal2003とAccess2000が混在しているPCで、初めてOfficeを使うWindowsユーザでログオンし Excel を起動すると、インストーラウィザードが立ち上がり以下のようなエラーが表示されました。

エラー 1706. CD-ROM またはネットワーク上に製品 Microsoft Access 2000 をインストールするのに必要なファイルが見つかりません。 Windows インストーラはインストールを継続できません。


とりあえずエラー番号でググッてみたら、MSサポート:[OFF2000] 機能の追加中にエラー1706が発生する現象についてという情報があったんで試したんですが、解決しませんでした。
よくよく考えたらこのユーザはAdministratorsグループに属しているので、上記のサポート情報は関係ありません。

で、試しに、Access2000を先に起動して見ました。
使用者情報を入れるダイアログがあったので、そこで情報を入れてからAccessを終了し、Excelを起動したらエラーが出なくなりました。

どうやらAccess2000側に使用者情報が入ってなかったことが原因だったようです。
[PR]
by jehoshaphat | 2014-02-07 00:36 | 豆知識 | Trackback | Comments(0)