nginxでセッション維持するロードバランサを構築
はじめに
よくあるWEBサーバ+DBサーバを使用した、とあるサービスを作る事になった
そのサービスをリリース後は結構な利用人数になりそうだった
なので、負荷分散ができる環境に前もって準備をしておこうと思った
ただし管理画面があるので、とあるURL以下はセッション維持したい(Android、iOS等向けのAPIは振り分けて、ブラウザからの管理画面へのアクセスはセッション維持する)
nginxでロードバランサ的なことができるとは知っていたけど、セッション維持がどうやるか・・・
色々調べた結果、セッション維持はnginxにモジュールを追加することで出来そうだと分かった
以下のサイトを参考に環境を構築した
参考サイト
目次
ロードバランサの構成
- CentOS 7
- nginx-1.13.7
- 追加モジュール:nginx-sticky-module-ng-1.2.6
コンパイル環境の準備
更新やら、コンパイルに必要なパッケージ群をインストール
yum update yum install vim yum groupinstall 'Development Tools' yum install epel-release
nginxが必要としているパッケージをインストール
yum install perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel GeoIP GeoIP-devel
nginxのインストール
nginxのソースコードをダウンロード・展開する
cd /usr/local/src wget http://nginx.org/download/nginx-1.13.7.tar.gz && tar zxvf nginx-1.13.7.tar.gz
また、nginxのコンパイルに必要な「PCRE」、「zlib」、「OpenSSL」のソースコードをダウンロードする。
cd /usr/local/src wget https://ftp.pcre.org/pub/pcre/pcre-8.41.tar.gz && tar xzvf pcre-8.41.tar.gz wget https://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz wget https://www.openssl.org/source/openssl-1.1.0g.tar.gz && tar xzvf openssl-1.1.0g.tar.gz
展開し終わったら要らないので削除
rm -rf *.tar.gz
ロードバランサのモジュールのソースコードを以下のサイトのからダウンロードする
wget https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng/get/1.2.6.tar.gz -O nginx-sticky-module-ng-1.2.6.tar.gz && tar xzvf nginx-sticky-module-ng-1.2.6.tar.gz
解凍したら「nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d」というディレクトリになっていた。
あとで見直してもわかるように、ディレクトリ名を変更
mv nginx-goodies-nginx-sticky-module-ng-c78b7dd79d0d nginx-sticky-module-ng-1.2.6
manコマンドでnginxのマニュアルが見れるように以下の以下のコマンドを実行
cp /usr/local/src/nginx-1.13.7/man/nginx.8 /usr/share/man/man8 gzip /usr/share/man/man8/nginx.8
以下のコマンドでマニュアルが表示される
man nginx
nginxのディレクトリに移動し「configure」を実行
cd /usr/local/src/nginx-1.13.7 ./configure --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --modules-path=/usr/lib64/nginx/modules \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --pid-path=/var/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --user=nginx \ --group=nginx \ --build=CentOS \ --builddir=nginx-1.13.7 \ --with-select_module \ --with-poll_module \ --with-threads \ --with-file-aio \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_xslt_module=dynamic \ --with-http_image_filter_module=dynamic \ --with-http_geoip_module=dynamic \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_auth_request_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_degradation_module \ --with-http_slice_module \ --with-http_stub_status_module \ --http-log-path=/var/log/nginx/access.log \ --http-client-body-temp-path=/var/cache/nginx/client_temp \ --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ --with-mail=dynamic \ --with-mail_ssl_module \ --with-stream=dynamic \ --with-stream_ssl_module \ --with-stream_realip_module \ --with-stream_geoip_module=dynamic \ --with-stream_ssl_preread_module \ --with-compat \ --with-pcre=/usr/local/src/pcre-8.41 \ --with-pcre-jit \ --with-zlib=/usr/local/src/zlib-1.2.11 \ --with-openssl=/usr/local/src/openssl-1.1.0g \ --with-openssl-opt=no-nextprotoneg \ --with-debug \ --add-module=/usr/local/src/nginx-sticky-module-ng-1.2.6
コンパイルする
make
このときはコンパイルするとエラーが発生した
以下がエラーメッセージ
/usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c: 関数 ‘ngx_http_sticky_misc_md5’ 内: /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:152:15: エラー: ‘MD5_DIGEST_LENGTH’ が宣言されていません (この関数内での最初の使用) u_char hash[MD5_DIGEST_LENGTH]; ^ /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:152:15: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:152:10: エラー: 使用されない変数 ‘hash’ です [-Werror=unused-variable] u_char hash[MD5_DIGEST_LENGTH]; ^ /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c: 関数 ‘ngx_http_sticky_misc_hmac_md5’ 内: /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:189:15: エラー: ‘MD5_DIGEST_LENGTH’ が宣言されていません (この関数内での最初の使用) u_char hash[MD5_DIGEST_LENGTH]; ^ /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:190:12: エラー: ‘MD5_CBLOCK’ が宣言されていません (この関数内での最初の使用) u_char k[MD5_CBLOCK]; ^ /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:190:10: エラー: 使用されない変数 ‘k’ です [-Werror=unused-variable] u_char k[MD5_CBLOCK]; ^ /usr/local/src/nginx-sticky-module-ng-1.2.6/ngx_http_sticky_misc.c:189:10: エラー: 使用されない変数 ‘hash’ です [-Werror=unused-variable] u_char hash[MD5_DIGEST_LENGTH]; ^ cc1: all warnings being treated as errors
解決方法は、bitbucketのissuesにあった
(しばらくメンテナンスされていないっぽいけど、今後大丈夫なんだろうか・・・)
ファイル:ngx_http_sticky_misc.cのinclude部分に以下を追記
#ifndef MD5_DIGEST_LENGTH #include <openssl/md5.h> #endif #ifndef SHA_DIGEST_LENGTH #include <openssl/sha.h> #endif
改めて、コンパイルとインストールを実行
make make install
設定でモジュールがロードできるようにシンボリックリンクを作成
ln -s /usr/lib64/nginx/modules /etc/nginx/modules
以下のコマンドが実行できればOK
nginx -V
nginxのユーザを作成する
useradd --system --home /var/cache/nginx --shell /sbin/nologin --comment "nginx user" --user-group nginx
ちなみに、設定ファイルの確認は以下のコマンドで確認できる。
nginx -t
このコマンドを実行すると、「ディレクトリが作れねぇ!」みたいなエラーがでてくる
nginx: [emerg] mkdir() "/var/cache/nginx/client_temp" failed (2: No such file or directory)
このときは、「/var/cache/nginx」というディレクトリを作成する。
mkdir -p /var/cache/nginx
nginxの起動と自動起動
nginxを自動起動させるため、「/usr/lib/systemd/system/nginx.service」を作成する
vim /usr/lib/systemd/system/nginx.service
ファイルの中身はこんな感じ(参考サイトのコピペ)
[Unit] Description=nginx - high performance web server Documentation=https://nginx.org/en/docs/ After=network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=/var/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID [Install] WantedBy=multi-user.target
nginxの起動と自動起動の有効化
systemctl start nginx systemctl enable nginx
nginxの設定
管理画面のみセッションを維持したいので、ロードバランサの方式は、セッションを維持するタイプと維持しないタイプ2種類用意する
- keep_session_backends
- 管理画面用
- default_backends
- その他
upstream keep_session_backends { sticky; server 192.168.33.12:8080; server 192.168.33.13:8080; } upstream default_backends { server 192.168.33.12:8080; server 192.168.33.13:8080; }
「/example」以下は「default_backends」を使用し、 「/example/admin」以下は「keep_session_backends」を使用する設定
location /example { proxy_pass http://default_backends; } location /example/admin { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Port $server_port; proxy_redirect off; proxy_pass http://keep_session_backends; }
「/example/admin」内の「proxy_set_header」は、Webアプリでリダイレクトするときに、ドメイン・ポート番号が変わらないようにしている
参考サイト
全体はこんな感じ(コメントは削除)
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream keep_session_backends { sticky; server 192.168.33.12:8080; server 192.168.33.13:8080; } upstream default_backends { server 192.168.33.12:8080; server 192.168.33.13:8080; } server { listen 8888; server_name localhost; port_in_redirect on; location /example { proxy_pass http://default_backends; } location /example/admin { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Port $server_port; proxy_redirect off; proxy_pass http://keep_session_backends; } error_page 404 /404.html; location = /404.html { root html; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
※ポート番号は、開発環境のため、8888番を使用
終わりに
「example/admin」以外の「example」以下には、交互にアクセスし、「example/admin」以下には片方のみアクセスするのを確認できた。
ちなみに今回使用した追加モジュールの「nginx-sticky-module-ng」は、2016年08月09日以降コミットがない・・・
nginxのバージョンが上がったときに、ちゃんと動作するのか心配
CentOS6にTomcat8.5をインストール&自動起動設定
はじめに
とあるプロジェクトで、Java(Spring Boot)でWEBアプリケーションを作ることにした
開発中はWindows内の統合開発環境の組み込みサーバで、アプリの動作確認できる
しかし本運用は多分CentOSで、今までApache+PHPの環境構築しかやったことがなかったため、デプロイの方法とか全然わからない・・・
なので色々調査・検討のためCentOSにTomcatサーバをインストールしてみた
環境
Java8のインストール
以下のサイトにアクセスしてURLを取得
Java SE Development Kit 8 - Downloads
wgetでrpmをダウンロードする。(「Accept License Agreement」が選ばれていないとダウンロードできないので色々オプションを追加している)
# wget --no-check-certificate --no-cookies - --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.rpm # rpm -Uvh jdk-8u131-linux-x64.rpm
以下のコマンドでインストールされたか確認
# java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
Tomcatのインストール
Tomcatのインストール先を「/opt/tomcat」にするためディレクトリを作成
# mkdir /opt/tomcat
以下のページにアクセスして、ダウンロードするファイルのURLを取得
Apache Tomcat® - Apache Tomcat 8 Software Downloads
Javaのrpmと同じようにwgetでTomcatをダウンロードしアーカイブを展開する
# cd /opt/tomcat # wget http://www-eu.apache.org/dist/tomcat/tomcat-8/v8.5.16/bin/apache-tomcat-8.5.16.tar.gz # tar xvf apache-tomcat-8.5.16.tar.gz
環境変数の追加
Tomcatに必要な環境変数が読み込まれるように「/etc/profile.d/tomcat.sh」を新規作成する
「/etc/profile.d/tomcat.sh」に以下を追記する
JRE_HOME=/usr/java/default CATALINA_HOME=/opt/tomcat/apache-tomcat-8.5.16 export JRE_HOME CATALINA_HOME
現在のターミナルに環境変数を適用
# . /etc/profile
Tomcat起動
以下のコマンドでTomcatを起動する
# /opt/tomcat/apache-tomcat-8.5.16/bin/startup.sh
外部からアクセスするためiptablesの修正。以下をsshの設定あたりに追加
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
ブラウザからアクセスするとTomcatのページが表示される
ちなみにTomcatの停止は以下のコマンド
# /opt/tomcat/apache-tomcat-8.5.16/bin/shutdown.sh
起動スクリプトの作成
なので、以下のサイトをパクって参考に起動スクリプトを作成
「/etc/init.d/tomcat」を新規作成
# vim /etc/init.d/tomcat
スクリプトの中身
#!/bin/sh # # chkconfig: 2345 85 15 # description: My Tomcat auto start # . /etc/rc.d/init.d/functions . /etc/profile.d/tomcat.sh case "$1" in start) echo -n "Tomcat starting..." ${CATALINA_HOME}/bin/startup.sh ;; stop) echo -n "Tomcat stopping..." ${CATALINA_HOME}/bin/shutdown.sh ;; restart) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit 0
# chmod 755 /etc/init.d/tomcat # chkconfig --add tomcat # chkconfig --list tomcat(起動するランタイムの確認)
CentOSを再起動しても8080にアクセスするとTomcatのページが表示される
おわりに
とりあえず今回はTomcatのインストール・自動起動の設定までやった
本運用のためには他にもポート番号の変更・logrotate等の設定等やらないといけないと思うが、また別の機会に実施しようと思う
【VB.NET】Windowsのタスクバーを非表示にした
はじめに
とあるアプリの仕様上、Windowsのタスクバーを非表示にしたくなった。
調べてみると、意外とコーディング方法がなく(XP時代のコードがでてきた)、また参考にしたコードもちょっと問題があった。
一応やりたいことが出来たのでメモ書き
環境
- VB.NET
- .NET Framework (バージョン忘れた・・・思い出し次第修正予定)
- WPF
実装
以下のサイトを参考にした。
Windowsのタスクバーの表示・非表示をAPIで制御する方法。(自動的に隠す隠さないもあるよ)
参考にしたサイトのものをそのまま使用すると、Windowsのスタートボタン(?)が残っていた
「WinLister」というツールを使用したところ、スタートボタンのウィンドウクラス名が「Button」っぽい
なので、「Shell_TrayWnd」と「Button」を非表示にするようにしたところ、タスクバーがちゃんと消えるようになった
以下、タスクバーを非表示にするクラス
Imports System.Runtime.InteropServices Class TaskbarControl ''' <summary>ウィンドウクラス名を格納しておく</summary> Private windowClasses As String() = New String() {"Shell_TrayWnd", "Button"} ''' <summary>タスクバー非表示前の状態保存用変数</summary> Private lastStatus As Dictionary(Of IntPtr, ABMsg) = New Dictionary(Of IntPtr, ABMsg) ''' <summary>タスクバーを表示します。</summary> Public Sub Show() SetVisible(True) End Sub ''' <summary>タスクバーを非表示にします。</summary> Public Sub Hidden() SetVisible(False) End Sub ''' <summary>タスクバーの表示・非表示切り替え</summary> ''' ''' <param name="visible">trueのとき表示する</param> Private Sub SetVisible(visible As Boolean) For Each className As String In windowClasses Dim hWnd As IntPtr = FindWindow(className, Nothing) If hWnd = 0 Then Continue For End If ' 非表示にする際は、「表示」している状態のAutoHideのOn・Offを同じ設定にするため、 ' メンバ変数に現在の状態を保存する。非表示から表示状態にするときは、保存していた ' 前回値を設定する。 Dim appbarMessage As ABMsg If visible Then If Me.lastStatus.ContainsKey(hWnd) Then appbarMessage = Me.lastStatus(hWnd) Else appbarMessage = ABMsg.ABM_NEW End If Else Dim status As ABMsg = Me.GetAppBarStatus(hWnd) Me.lastStatus.Add(hWnd, status) appbarMessage = ABMsg.ABM_REMOVE End If Me.SetAppBarStatus(hWnd, ABMsg.ABM_ACTIVATE) Dim command As Integer = If(visible, WindowCmd.Show, WindowCmd.Hide) ShowWindow(hWnd, command) Next If visible Then Me.lastStatus.Clear() End If End Sub ''' <summary>タスクバーの状態を取得</summary> ''' ''' <param name="hWnd">ウィンドウハンドル</param> ''' <returns>タスクバーの表示状態</returns> Private Function GetAppBarStatus(hWnd As IntPtr) As ABMsg Dim pData As New APPBARDATA() pData.cbSize = Marshal.SizeOf(pData) pData.hWnd = hWnd SHAppBarMessage(ABMsg.ABM_GETSTATE, pData) Return pData.lParam End Function ''' <summary>タスクバーの状態を設定</summary> ''' ''' <param name="hWnd">ウィンドウハンドル</param> ''' <param name="status">AppBarメッセージ</param> Private Sub SetAppBarStatus(hWnd As IntPtr, status As ABMsg) Dim pData As New APPBARDATA() pData.cbSize = Marshal.SizeOf(pData) pData.hWnd = hWnd pData.lParam = status SHAppBarMessage(ABMsg.ABM_SETSTATE, pData) End Sub ''' <summary>Sends an appbar message to the system.</summary> Private Enum ABMsg As Integer ''' <summary>Registers a new appbar and specifies the message identifier that the system should use to send notification messages to the appbar.</summary> ABM_NEW = 0 ''' <summary>Unregisters an appbar, removing the bar from the system's internal list.</summary> ABM_REMOVE = 1 ''' <summary>Requests a size and screen position for an appbar.</summary> ABM_QUERYPOS = 2 ''' <summary>Sets the size and screen position of an appbar.</summary> ABM_SETPOS = 3 ''' <summary>Retrieves the autohide and always-on-top states of the Windows taskbar.</summary> ABM_GETSTATE = 4 ''' <summary>Retrieves the bounding rectangle of the Windows taskbar. </summary> ''' ''' <remarks> ''' Note that this applies only to the system taskbar. ''' Other objects, particularly toolbars supplied with third-party software, also can be present. ''' As a result, some of the screen area not covered by the Windows taskbar might not be visible to the user. ''' To retrieve the area of the screen not covered by both the taskbar ''' and other app bars—the working area available to your application—, ''' use the GetMonitorInfo function. ''' </remarks> ABM_GETTASKBARPOS = 5 ''' <summary>Notifies the system to activate or deactivate an appbar.</summary> ''' ''' <remarks> ''' The lParam member of the APPBARDATA pointed to by pData is set to TRUE to activate or FALSE to deactivate. ''' </remarks> ABM_ACTIVATE = 6 ''' <summary>Retrieves the handle to the autohide appbar associated with a particular edge of the screen.</summary> ABM_GETAUTOHIDEBAR = 7 ''' <summary>Registers or unregisters an autohide appbar for an edge of the screen.</summary> ABM_SETAUTOHIDEBAR = 8 ''' <summary>Notifies the system when an appbar's position has changed.</summary> ABM_WINDOWPOSCHANGED = 9 ''' <summary>Sets the state of the appbar's autohide and always-on-top attributes.</summary> ''' ''' <remarks> ''' Windows XP and later ''' </remarks> ABM_SETSTATE = 10 ''' <summary>Retrieves the handle to the autohide appbar associated with a particular edge of a particular monitor.</summary> ''' ''' <remarks> ''' Windows XP and later ''' </remarks> ABM_GETAUTOHIDEBAREX = 11 ''' <summary>Registers or unregisters an autohide appbar for an edge of a particular monitor.</summary> ''' ''' <remarks> ''' Windows XP and later ''' </remarks> ABM_SETAUTOHIDEBAREX = 12 End Enum ''' <summary>Contains information about a system appbar message.</summary> ''' ''' <remarks> ''' http://www.geocities.jp/katayama_hirofumi_mz/imehackerz/ja/APPBARDATA.html ''' </remarks> <StructLayout(LayoutKind.Sequential)> Private Structure APPBARDATA ''' <summary>The size of the structure, in bytes.</summary> Public cbSize As Integer ''' <summary>The handle to the appbar window.</summary> ''' ''' <remarks> ''' Not all messages use this member. See the individual message page to see if you need to provide an hWind value. ''' </remarks> Public hWnd As IntPtr ''' <summary>An application-defined message identifier.</summary> ''' ''' <remarks> ''' The application uses the specified identifier for notification messages ''' that it sends to the appbar identified by the hWnd member. ''' This member is used when sending the ABM_NEW message. ''' </remarks> Public uCallbackMessage As UInteger ''' <summary>A value that specifies an edge of the screen.</summary> ''' ''' <remarks> ''' This member is used when sending one of these messages:<br/> ''' <list type="bullet"> ''' <item>ABM_GETAUTOHIDEBAR</item> ''' <item>ABM_SETAUTOHIDEBAR</item> ''' <item>ABM_GETAUTOHIDEBAREX</item> ''' <item>ABM_SETAUTOHIDEBAREX</item> ''' <item>ABM_QUERYPOS</item> ''' <item>ABM_SETPOS</item> ''' </list> ''' </remarks> Public uEdge As ABEdge ''' <summary>A RECT structure</summary> ''' ''' <remarks> ''' A RECT structure whose use varies depending on the message:<br/> ''' ABM_GETTASKBARPOS、ABM_QUERYPOS、ABM_SETPOS: ''' The bounding rectangle, in screen coordinates, of an appbar or the Windows taskbar. ''' ABM_GETAUTOHIDEBAREX、ABM_SETAUTOHIDEBAREX ''' The monitor on which the operation is being performed. This information can be retrieved through the GetMonitorInfo function. ''' </remarks> Public rc As RECT ''' <summary>A message-dependent value.</summary> ''' ''' <remarks> ''' This member is used with these messages:<br/> ''' <list type="bullet"> ''' <item>ABM_SETAUTOHIDEBAR</item> ''' <item>ABM_SETAUTOHIDEBAREX</item> ''' <item>ABM_SETSTATE</item> ''' </list> ''' See the individual message pages for details. ''' </remarks> Public lParam As Integer End Structure ''' <summary>A value that specifies an edge of the screen.</summary> Private Enum ABEdge As Integer ''' <summary>Left edge.</summary> ABE_LEFT = 0 ''' <summary>Top edge.</summary> ABE_TOP = 1 ''' <summary>Right edge.</summary> ABE_RIGHT = 2 ''' <summary>Bottom edge.</summary> ABE_BOTTOM = 3 End Enum ''' <summary>the coordinates of the upper-left and lower-right corners of a rectangle.</summary> <StructLayout(LayoutKind.Sequential)> Private Structure RECT ''' <summary>The x-coordinate of the upper-left corner of the rectangle.</summary> Public left As Integer ''' <summary>The y-coordinate of the upper-left corner of the rectangle.</summary> Public top As Integer ''' <summary>The x-coordinate of the lower-right corner of the rectangle.</summary> Public right As Integer ''' <summary>The y-coordinate of the lower-right corner of the rectangle.</summary> Public bottom As Integer End Structure ''' <summary>ウィンドウの表示方法</summary> ''' ''' <remarks> ''' https://msdn.microsoft.com/ja-jp/library/cc411211.aspx ''' </remarks> Private Enum WindowCmd As Integer ''' <summary>表示</summary> Hide = 0 ''' <summary>非表示</summary> Show = 5 End Enum ''' <summary>システムにAppBarメッセージを送信する。</summary> ''' ''' <remarks> ''' https://msdn.microsoft.com/ja-jp/library/bb762108(v=vs.85).aspx ''' </remarks> ''' ''' <param name="dwMessage">AppBarメッセージ値</param> ''' <param name="pData">送信パラメータ</param> ''' ''' <returns>メッセージに依存した値</returns> <DllImport("shell32.dll", CallingConvention:=CallingConvention.StdCall)> Private Shared Function SHAppBarMessage(dwMessage As ABMsg, ByRef pData As APPBARDATA) As Integer End Function ''' <summary>指定されたウィンドウの表示状態を設定します。</summary> ''' ''' <remarks> ''' https://msdn.microsoft.com/ja-jp/library/cc411211.aspx ''' </remarks> ''' ''' <param name="hWnd">ウィンドウハンドル</param> ''' <param name="nCmdShow">表示状態</param> ''' ''' <returns>ウィンドウが以前から表示されていた場合は、0 以外の値</returns> <DllImport("user32.dll", EntryPoint:="ShowWindow")> Private Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Integer End Function ''' <summary>指定された文字列と一致するクラス名とウィンドウ名を持つ親を持たないウィンドウのハンドルを返します</summary> ''' ''' <remarks> ''' https://msdn.microsoft.com/ja-jp/library/cc364634.aspx ''' </remarks> ''' ''' <param name="lpClassName">クラス名</param> ''' <param name="lpWindowName">ウィンドウ名</param> ''' ''' <returns>関数が成功すると、指定したクラス名とウィンドウ名を持つウィンドウのハンドルが返ります</returns> <DllImport("user32.dll", EntryPoint:="FindWindow")> Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As Integer End Function End Class
使用例
使用方法はこんな感じ
Class MainWindow Private taskbarController As TaskbarControl = New TaskbarControl() ''' <summary>画面表示時に実行</summary> Private Sub Grid_Loaded(sender As Object, e As RoutedEventArgs) Me.Left = 0 Me.Top = 0 Me.Width = SystemParameters.PrimaryScreenWidth Me.Height = SystemParameters.PrimaryScreenHeight Me.Topmost = True taskbarController.Hidden() End Sub ''' <summary>アプリ終了時に実行</summary> Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs) taskbarController.Show() End Sub End Class
動作確認はWindows7(64bit)、Windows10(うろ覚え・・・)
C#版も作ったけど、タスクバーの復帰がうまくいかなかった・・・
具体的には、タスクバーを「自動的に隠す」にした後に、非表示→表示と動作させると「自動的に隠す」の設定が消えてる・・・VBだと問題なかったんだけど
C#版で作ったことはなかったことにしよう