セルのA1から右へ向かって以下のように入力する。
0,=DEC2HEX(A1),=CHAR(A1+97),=CHAR(A1+65)
これで16進数と、小文字アルファベットと大文字アルファベットのAutoFillができる。
優先度と言えば通常はCPUの優先度で、これを低く設定するとそのプロセスはCPUを使いづらくなる。あるメインのタスクがあってそれを重点的にやりたい場合、このタスクの優先度を上げて、これとは別の忙しそうなタスクの優先度を下げる。こうすることによりメインのタスクは他のタスクに邪魔されずにスムーズに作業が進む。
しかしCPUの優先度を下げてもそのプロセスが大量のデータをハードディスクでやり取りしているとうまくいかなくなる。メインタスクがハードディスクにアクセスしようとしてもCPUの優先度はこの場合関係がないので、待たされることになり作業が捗らない。
そこで使うのがIOの優先度なのだが、WindowsにしてもLinuxにしてもドキュメントやAPI整備が整っていない。
もっともよくドキュメントが整備されているのがSetPriorityClass()で指定できるバックグラウンド設定だ。この設定だけは他の設定と違い、BEGINとENDで開始と終了を指定する。なぜこんなことになっているのかといえばバックグラウンドの設定だけはCPUだけじゃなくIO優先度や他の優先度(メモリ)も変更するからだと思われる。しかし制限もあり、バックグラウンドの場合だけは他のプロセスの設定を変更できない(実際にエラーになる)。
そこでこれを実現したいのだがドキュメントがないのでネットで調べるとntdll.dllで定義されるNtSetInformationProcessを使うことがわかった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// http://blog.misterfoo.com/2010/07/process-priority-utility.html // these values determined by poking around in the debugger - use at your own risk! const DWORD ProcessInformationMemoryPriority = 0x27; const DWORD ProcessInformationIoPriority = 0x21; const DWORD DefaultMemoryPriority = 5; const DWORD LowMemoryPriority = 3; const DWORD DefaultIoPriority = 2; const DWORD LowIoPriority = 1; const DWORD VeryLowIoPriority = 0; typedef NTSTATUS(NTAPI *FNNtSetInformationProcess)( HANDLE process, ULONG infoClass, void* data, ULONG dataSize); |
この関数は挙動が不明なところがあって、デバッガでステップオーバーすると失敗するが、普通に実行すると成功したりする。この関数でメモリとIOの優先度を変更できる。
IOの優先度を最低にするには以下のように行う。
1 2 3 4 5 6 |
ULONG io = VeryLowIoPriority; ntStatus = fnNtSetInformationProcess( hProcess, ProcessInformationIoPriority, &io, sizeof(io)); |
0が返ってくれば成功。hProcessをOpenProcess()で取得する場合はフラグにPROCESS_SET_INFORMATIONを指定して開く。
Linuxの場合はコマンドのioniceがあるので、このソースを見ればいい。しかしこれもドキュメントやヘッダファイルがないようである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
static inline int ioprio_set(int which, int who, int ioprio) { return syscall(SYS_ioprio_set, which, who, ioprio); } enum { IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE, }; enum { IOPRIO_WHO_PROCESS = 1, IOPRIO_WHO_PGRP, IOPRIO_WHO_USER, }; #define IOPRIO_CLASS_SHIFT (13) #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) |
ioniceから持ってきたであろう上のソースをコピペして以下のように呼ぶ。
1 2 |
int ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE,7); err = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio); |
ioprioは2つの値DATAとCLASSから構成されていてCLASSで優先度を指定する。DATAはスルー。Linuxの場合、優先度をある程度上げるときはroot権限が必要な模様でその失敗の場合-1が返る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function isLocalIp($ip) { // check whether ip address if ( ! filter_var($ip, FILTER_VALIDATE_IP) ) { // not an ip address return false; } // https://stackoverflow.com/a/12439589 if ( ! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) ) { // is a local ip address return true; } return false; } |
filter_varでいろいろな条件を調べられる。メールアドレスとかドメインとか、あるいはboolとして1や”yes”,”on”なども調べられる。
この関数ではまずIPアドレスかどうかを調べて、つぎにそれがプライベートか予約されたアドレスかどうかの条件を追加して調べている。
FILTER_FLAG_NO_PRIV_RANGEを指定すると、プライベートでないものはfalseを返す。マニュアルによると以下。
Fails validation for the following private IPv4 ranges: 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.
Fails validation for the IPv6 addresses starting with FD or FC.
FILTER_FLAG_NO_RES_RANGEを指定すると、予約されたアドレスでない場合はfalseを返す。マニュアル以下。
Fails validation for the following reserved IPv4 ranges: 0.0.0.0/8, 169.254.0.0/16, 127.0.0.0/8 and 240.0.0.0/4.
Fails validation for the following reserved IPv6 ranges: ::1/128, ::/128, ::ffff:0:0/96 and fe80::/10.
フィルタの一覧
http://php.net/manual/en/filter.filters.validate.php
–ignore-certificate-errorsをつける
constが必要なのになかったり、その逆だとこんなエラーがでる。テンプレートで出る。
1 |
Project ERROR: Failed to run: 'lrelease.exe' |
64ビットWindowsを使っていて、32ビットのコマンドプロンプトやエクスプローラからqmake関係を起動するとおかしくなることがある。qmakeに限らず、64ビット環境での64ビットアプリと32ビットアプリでは環境変数などが一部異なるので、ビルド環境では64ビットの純正コマンドプロンプトやエクスプローラを使ったほうがよい。
コモンコントロールとはWindowsOSによって提供される基本的な機能を持ったウインドウ。ツリーやリストなど。コモンコントロールはバージョンアップが重ねられており、バージョンの違いでヘッダファイルにも違いが出る。開発環境と実行環境で違うバージョンがインストールされている場合もある。コモンコントロールはIEのインストールでバージョンアップされる。
https://msdn.microsoft.com/en-us/library/windows/desktop/hh298349(v=vs.85).aspx
1 2 3 4 |
5.81 Microsoft Internet Explorer 5.01, Microsoft Internet Explorer 5.5, and Microsoft Internet Explorer 6 5.82 Windows Server 2003, Windows Vista, Windows Server 2008, and Windows 7 6.0 Windows Server 2003 6.10 Windows Vista, Windows Server 2008, and Windows 7 |
実体はComCtl32.dll。C:\Windows\System32\ComCtl32.dllにある。
C言語のヘッダファイルでは_WIN32_IEにより、構造体などの定義が変わる。多くの構造体はそのサイズを持ち、この値がどんどん増えていく。この定数は_WIN32_WINNTの設定によって自動で設定される。_WIN32_WINNTを設定しなければ0x0500(version 5.80)になるようだ。SDKによって変わる。参照
コモンコントロールのDLLがウインドウクラスを登録し、ユーザはこのクラスでCreateWindowExすることにより作成する。 InitCommonControlsEx()を呼ぶと、クラスの登録が行われるがDLLのロード時に行われるのかもしれない。
Visual Stylesはコモンコントロールの表示スタイル(見栄え)を変える。
コモンコントロールの言語を変えるにはInitMUILanguage()を呼ぶ。
ComCtrl32.dllはハードリンクされている。
1 2 3 4 5 6 7 8 9 10 |
>fsutil hardlink list c:\Windows\System32\comctl32.dll \Windows\WinSxS\amd64_microsoft-windows-shell-comctl32-v5_31bf3856ad364e35_10.0.16299.15_none_5c884af3491bf6a4\comctl32.dll \Windows\System32\comctl32.dll > >fsutil hardlink list c:\Windows\SysWOW64\comctl32.dll \Windows\SysWOW64\comctl32.dll \Windows\WinSxS\x86_microsoft-windows-shell-comctl32-v5_31bf3856ad364e35_10.0.16299.15_none_0069af6f90be856e\comctl32.dll > |
WinSxSはサイドバイサイドのアセンブリが置かれているところで長い名前はComCtrl32.dllのアセンブリアイデンティを表している。アプリケーションが特定のバージョンのdllを読み込みたい場合はマニフェストにこのアイデンティを指定する。
1 2 3 |
#pragma comment(linker,"\"/manifestdependency:type='win32' \ name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") |
このpragmaのつけたexeを起動すると、C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.16299.371_none_5d75084fa7e1cb96\comctl32.dllが使われる。このファイルはハードリンクをこの1つしか持っていない。ver6のコモンコントロールを使うにはマニフェストで指定するしかないことになる。
1 |
$ explorer . |
これは普通に動くが、かなり特殊条件もあって動いている。explorerは起動されたプロセスが開くのではなかったり(開く場合もある)、”.”を理解してちゃんと開いてくれる。それにcygpath(cygwinの形態のパス変換)の問題もない。
TEはプロセスがなければ自分で開くのでcygwinシェルから普通に起動するとシェルがブロックする。&をつけてバックグラウンドで動かしてもシェルがプロセスを管理しているため、cygwinの終了と同時に終了してしまう。nohubを使う手もあるかもしれないがここではスルー。
プロセスの起動はコマンドプロンプトのstartコマンドで行えばプロセス起動後すぐに終了するので上記の問題はない。しかしstartはビルドインプロセスのようでcygwinからは起動できない。そこでcmd /C startで起動すればいい。
パスの返還はcygwinのcygpath -waコマンドで行う。-aはフルパス、-wはWindows形態に変える。
よってカレントディレクトリをTE32.exeで開くには以下のように行う。
1 |
$ cmd /C start '""' `cygpath -wa /cygdrive/C/pathto/TE32.exe` `cygpath -wa .` |
‘””‘はstartに””を送っている。startコマンドの性質上こうしている。
これでcygwinシェルから切り離されたプロセスと起動できたが何らかの環境変数などは継承しているかもしれない。
上記のコマンドはパスにスペースが含まれた場合を考慮していないので、その場合は””でくくらないとならないと思う。
qmakeのproファイルの書き方
hello.proを作成すると、プロジェクト名がhelloになり出来上がる実行ファイル名もhello.exeになる。
SOURCES変数にファイルを追加する。
1 2 |
SOURCES += main.cpp SOURCES += hello.cpp |
スペースで区切って複数指定してもいい、\ (バックスラッシュ)を行末につけて複数行にすることもできる。
1 2 |
SOURCES = main.cpp mainwindow.cpp \ paintwidget.cpp |
HEADERS変数にファイルを追加する。
1 |
HEADERS += header.h |
1 2 3 4 5 6 |
win32 { SOURCES += hellowin.cpp } unix { SOURCES += hellounix.cpp } |
{ は条件と同じラインに書かなければならない。
1 2 3 |
!exists( main.cpp ) { error( "No main.cpp file found" ) } |
CONFIG変数にdebugと設定する。
1 |
CONFIG += debug |
1 2 3 |
win32:debug { CONFIG += console } |
変数は自分で書いてもいい。参照するには $$ を用いる。
1 |
TEMP_SOURCES = $$SOURCES |
1 2 |
win32:INCLUDEPATH += "C:/mylibs/extra headers" unix:INCLUDEPATH += "/home/user/extra headers" |
# で始めるとコメントになる。
1 2 |
# Comments usually start at the beginning of a line, but they # can also follow other content on the same line. |
TEMPLATE変数を使う。
デフォルトはapp
QT変数を使う。
1 |
QT += network xml |
coreとguiはデフォルトで設定される。デフォルトから外したいときは += ではなく = を使う。あるいは -= を使う。
1 |
QT -= gui # Only the core module is used. |
Featureとは.prfで記述される特別な機能。CONFIGに機能を設定して使用する。
1 2 |
CONFIG += link_pkgconfig PKGCONFIG += ogg dbus-1 |
pkg-configを利用して、D-Busとoggライブラリを利用する。
1 |
LIBS += -L/usr/local/lib -lmath |
ライブラリをつくるにはTEMPLATE変数にlibを設定する。そのうえでCONFIG変数でライブラリのタイプを指定する。
$$(ENVVAL)を使う。
1 2 |
DESTDIR = $$(PWD) message(The project will be installed in $$DESTDIR) |