Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

Determine whether you are behind a proxy or not with .NET

You can get the default proxy setting for a specific url with System.Net.WebRequest.GetSystemWebProxy().GetProxy().

The result is System.Uri object, and its OriginalString property will be the same the parameter if you are not behind a proxy:

PS C:\> [System.Net.WebRequest]::GetSystemWebProxy().GetProxy('https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize')


AbsolutePath   : /organizations/oauth2/v2.0/authorize
AbsoluteUri    : https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize
LocalPath      : /organizations/oauth2/v2.0/authorize
Authority      : login.microsoftonline.com
HostNameType   : Dns
IsDefaultPort  : True
IsFile         : False
IsLoopback     : False
PathAndQuery   : /organizations/oauth2/v2.0/authorize
Segments       : {/, organizations/, oauth2/, v2.0/...}
IsUnc          : False
Host           : login.microsoftonline.com
Port           : 443
Query          :
Fragment       :
Scheme         : https
OriginalString : https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize
DnsSafeHost    : login.microsoftonline.com
IdnHost        : login.microsoftonline.com
IsAbsoluteUri  : True
UserEscaped    : False
UserInfo       :

The OriginalString property will be the same the proxy URL if if you are behind a proxy:

PS C:\> [System.Net.WebRequest]::GetSystemWebProxy().GetProxy('https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize')


AbsolutePath   : /
AbsoluteUri    : http://140.227.25.56:5678/
LocalPath      : /
Authority      : 140.227.25.56:5678
HostNameType   : IPv4
IsDefaultPort  : False
IsFile         : False
IsLoopback     : False
PathAndQuery   : /
Segments       : {/}
IsUnc          : False
Host           : 140.227.25.56
Port           : 5678
Query          :
Fragment       :
Scheme         : http
OriginalString : http://140.227.25.56:5678
DnsSafeHost    : 140.227.25.56
IdnHost        : 140.227.25.56
IsAbsoluteUri  : True
UserEscaped    : False
UserInfo       :

JDBCドライバがサーバとの1回の通信で取得する行数のデフォルト値

  • Oracle 11.2は10行。*1

    By default, when Oracle JDBC runs a query, it retrieves a result set of 10 rows at a time from the database cursor. This is the default Oracle row fetch size value.

  • Oracle 21は10行。*2

    By default, when Oracle JDBC runs a query, it retrieves a result set of 10 rows at a time from the database cursor. This is the default Oracle row fetch size value.

  • PostgreSQLは全行を一気に取得する。*3

    By default the driver collects all the results for the query at once.

  • MySQL Connector/J 8.0は全行を一気に取得する。*4

    By default, ResultSets are completely retrieved and stored in memory. In most cases this is the most efficient way to operate and, due to the design of the MySQL network protocol, is easier to implement. If you are working with ResultSets that have a large number of rows or large values and cannot allocate heap space in your JVM for the memory required, you can tell the driver to stream the results back one row at a time.

  • HiRDB 09-50以前は1行。HiRDB 09-50以降は10キロバイトぶん。*5

    バージョン09-50で、ブロック転送機能はデフォルトで有効となります。ユーザがブロック転送機能の指定を何もしない場合、PDBLKBUFFSIZEの省略値が10キロバイトとなります。

  • Microsoft JDBC Driver for SQL Server 1.2までは全行を一気に取得する。Microsoft JDBC Driver for SQL Server 2.0以降は"adaptive"に取得する。*6

    Starting with the JDBC driver version 2.0, the default behavior of the driver is "adaptive". In other words, in order to get the adaptive buffering behavior, your application does not have to request the adaptive behavior explicitly. In the version 1.2 release, however, the buffering mode was "full" by default and the application had to request the adaptive buffering mode explicitly.

Test-NetConnectionの不思議な挙動

最近はICMP Echoに応答しないサイトも多い(たとえばlogin.live.com)。そんなときは、TCPでポートを指定して接続確認が行えるTest-NetConnectionコマンドレットが便利に使える。

ただこのTest-NetConnectionコマンドレット、ネットワーク接続が確立していない場合に妙な挙動をすることが多いみたい。

名前解決は可能だが接続先ホストに到達できない場合(VPN接続確立前など)

名前解決は可能だが接続先ホストに到達できない場合、Test-NetConnectionは名前解決で返ってきたすべてのAレコードのIPアドレスに対して接続を試みるように見える。ラウンドロビンという観点から見れば正しいと言えば正しいのだが、AレコードがいっぱいあるFQDNだとエラーが大量に出て鬱陶しい。

名前解決もできない場合(WiFi AP接続前など)

名前解決もできない場合、Test-NetConnectionは使用できるすべてのNICで通信を試みるように見える。有線LANと無線LANとWSLの仮想NICVMWareの仮想NICBluetoothネットワークと……と環境によっては結構な数のエラーが出るため、こちらはこちらでやはり鬱陶しい。

You cannot identify platforms of an application that is about to authenticate

Background

  • You are trying to write an authentication logic for an application that calls a Microsoft Graph API.
  • When you retrieve an authentication token, you have to pass client secret if the application is registerd with "Web" platform configuration (otherwise you will get AADSTS7000218 error). On the other hand, you must not pass client secret if the application is registerd with "Movile and desktop application" platform configuration (otherwise you will get AADSTS700025 error). *1
  • You can get the platform configuration of an application with Microsoft Graph API. You will see web property in the result of GET /applications. *2

Problem

To call GET /applications API endpoint, you have to authenticate the application. Also you have to give one of Application.Read.All, Application.ReadWrite.All, Directory.AccessAsUser.All, or Directory.Read.All permission.

So you cannot identify platforms of an application that is about to authenticate.

OneDriveにMicrosoft Graph APIでアクセスする

  • OAuth2のトークンを取得する際にtenantを指定する*1のだが、これはOneDriveのURLのhttps://XXXXX-my.sharepoint.com/のところに入るテナント名とは別で、commonorganizationsconsumersを指定するとある。commonを指定しているドキュメント*2を参考にしてみたら以下のAADSTS50194エラーが返ってきたのでorganizationsを指定するよう変更した。

    AADSTS50194: Application 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'(ApplicationName) is not configured as a multi-tenant application. Usage of the /common endpoint is not supported for such applications created after '10/15/2018'. Use a tenant-specific endpoint or configure the application to be multi-tenant.

  • APIのパスとファイルのパスと操作のパスをコロンで区切る。たとえば自分自身のOneDriveの/path/to/folderというフォルダ以下で、パスに03を含むファイルやフォルダを検索したい場合は https://graph.microsoft.com/v1.0/me/drive/root:/path/to/folder:/search(q='03') となる。このへんの考えかたがAPIドキュメントの概要のページ*3とかに全然書かれていない。
  • APIのドキュメントにGET /me/drive/items/{item-id}など{item-id}というメタ構文が出てくる場合がある*4。アイテムにIDベースでアドレス指定でアクセスできる*5とドキュメントには記載があるが、APIで取得したJSONの中にあるidをこの{item-id}に入れてもアクセスできなかった。結局パスベースでアクセスすることにした。
  • /FolderA/FolderB/Foobar.jpgというファイルを作りたい場合、特に前準備なしで/FolderA/FolderB/Foobar.jpgというパスでアップロードすればよい。前もって/FolderA/FolderBというフォルダを作る必要はない。ファイルのアップロードが成功したら/FolderA/FolderBというフォルダが勝手に作られる。
  • ファイルをアップロードすることなしに複数階層のフォルダを一気に作りたい場合はPATCHメソッドでリクエストを送ればいいみたい*6。ただ、手元で試したところ単発では成功したがスクリプト中で実行しようとすると失敗した(なぜだろう?)。