Quantcast
Channel: 蒼の王座・裏口
Viewing all 183 articles
Browse latest View live

SQL Server で、 datetimeデータ型から、日付部分のみを取得する方法

$
0
0

SELECT GETDATE()

上記クエリを実行すると、「2015-01-05 23:00:05」のように日付と時刻が返ってきます。

日付だけを取得したい場合にはどうしたらいいのでしょうか。

SQL Server 2008 以降であれば、つぎのクエリで取得できます。

SELECT CONVERT(date, getdate())

このクエリを実行すると、「2015-01-05」を取得することができます。


一つのSQLクエリで、複数の行をinsertする方法

$
0
0

一つのSQLクエリで、複数の行を追加するには、カンマでつなげればOKです。

SQL Server 2008では、次のようなクエリでOKです。

INSERT INTO Table ( C1, C2 ) VALUES ( Value1, Value2 ), ( Value1, Value2 )

一つのクエリで追加できる最大行は、1000行です。

ちなみに、SQL Server 2005では動作しないので、SQL Server 2005では次のような方法をとることになります。

INSERT INTO dbo.MyTable (C1, C2)
SELECT Value1, Value2
UNION ALL
SELECT Value1, Value2
UNION ALL
SELECT Value1, Value2

Cannot convert type ‘System.Uri’ to ‘string’の対応

$
0
0

次のようなクエリを書いたら暗黙的菜型変換に失敗しました。

Response.Redirect(response.ResponseUri.ToString());

エラーメッセージ

Cannot convert type ‘System.Uri’ to ‘string’

暗黙的な型変換ではダメ、次のような「(cast)response.ResponseUri」型変換もダメで、おとなしく「Tostring」を使用すればOK

Response.Redirect(response.ResponseUri.ToString());

RestSharpで、サンプルコードに従って書いたら型変換エラーがでた件

$
0
0

RestSharpのサンプルコードに従って書いたらエラーが出た。

RestResponse response = client.Execute(request);

エラー文面

Cannot implicitly convert type ‘IRestResponse’ to ‘RestResponse’. An explicit conversion exists (are you missing a cast?)

Dropbox API and RestSharp for a C# developerに対処方法が記載されていました。
次のように書き換えて対応しました。

var response = client.Execute(request);

SQL ServerでDateTimeからTimeを取得する方法

$
0
0

次のようなDateTime型のデータがあります。

Examle
==
2015-01-09 15:19:00
2015-01-09 14:10:00 

Timeだけを抽出して、次のような結果を取得する方法について説明します。

Examle
==
2015-01-09 15:19:00
2015-01-09 14:10:00 

SQL Server 2008

select cast(Example as time) [time] from table

SQL Server 2008以前

select convert(char(5), Example, 108) [time] from table

ASP.NET WEB API 2 のメモ

$
0
0

 ASP.NET Web APIは、モバイルデバイス、ブラウザ、クライアントアプリなどで、HTTPサービスを簡単に作ることができるフレームワーク。ASP.NET Web APIは、.NET Framework上で、RESTfulアプリケーションを構築するためのプラットフォーム。

Nugetで提供されている。

Install-Package Microsoft.AspNet.WebApi.Client

.NET で、POSTやGETなどのRESTful通信をしたいときに使うと手軽で実現可能。

こんな感じでかけるので素のPOST処理を書くのに比べると段違い。

using (var client = new HttpClient())
{     client.BaseAddress = new Uri(baseUrl);     client.DefaultRequestHeaders.Accept.Clear();     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));     var accesstoken = new accessToken(clientId, clientSecret, code);     HttpResponseMessage response = await client.PostAsJsonAsync("/api/v2/access_tokens", accesstoken);     if (response.IsSuccessStatusCode)     {         Uri gizmoUrl = response.Headers.Location;     }
}

Microsoft Intune で、SA権付きライセンスの提供が終了しておった

$
0
0

Microsoft Intuneには、SA権(ソフトウェアアシュアランス)ついていて、素晴らしい!のはずだったのだが、ひっそりと提供が終了していた(´・ω・`)

http://www.microsoft.com/ja-jp/server-cloud/products/microsoft-intune/buy.aspx

image

- Windows ソフトウェア アシュアランス付きライセンスの提供終了のお知らせ –
これまでマイクロソフト オンライン サブスクリプション契約で販売しておりました Windows ソフトウェア アシュアランス付き Microsoft Intune のライセンスの提供を、2014 年 12 月 31 日をもって終了いたします。
2014 年 12 月 31 日以前に同ライセンスを購入されたお客様は、更新により既存のライセンスをそのままご利用いただけますが、2015 年 1 月 1 日以降、ライセンス数を増加することはできません。

Chrome の拡張機能がセキュリティーエラーでインストールできない時の対応方法 (Mac編)

$
0
0

社内ツールとして、Chromeの拡張機能(Extension)を配布しているが、セキュリティ強化を目的としたChromeの仕様変更により、エラーでインストールできなくなった。

従来はポリシー(ExtensionInstallWhitelist や ExtensionInstallSources)で対応していたのだけど、Chrome 39辺りでもMac用Chromeで仕様変更あったみたいで、インストールできなくなった。それの対処方法。

次のような、「profile.mobileconfig」ファイルを用意する。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
   <dict>
      <key>PayloadIdentifier</key>
      <string>com.yourname.Angrybird</string>
      <key>PayloadRemovalDisallowed</key>
      <false />
      <key>PayloadScope</key>
      <string>System</string>
      <key>PayloadType</key>
      <string>Configuration</string>
      <key>PayloadUUID</key>
      <string>bde4dcb5-d4bf-4943-b992-c30f82eb1468</string>
      <key>PayloadOrganization</key>
      <string>com.gloops</string>
      <key>PayloadVersion</key>
      <integer>1</integer>
      <key>PayloadDisplayName</key>
      <string>com.gloops</string>
      <key>PayloadContent</key>
      <array>
         <dict>
            <key>PayloadType</key>
            <string>com.apple.ManagedClient.preferences</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>PayloadIdentifier</key>
            <string>com.yourname.Angrybird.f13e3b90-6187-0132-2314-685b357e505d</string>
            <key>PayloadUUID</key>
            <string>f13e3b90-6187-0132-2314-685b357e505d</string>
            <key>PayloadEnabled</key>
            <true />
            <key>PayloadDisplayName</key>
            <string>Google Chrome</string>
            <key>PayloadContent</key>
            <dict>
               <key>com.google.Chrome</key>
               <dict>
                  <key>Forced</key>
                  <array>
                     <dict>
                        <key>mcx_preference_settings</key>
                        <dict>
                           <key>ExtensionInstallWhitelist</key>
                           <array>
                              <string>epkhkajflhigkpbcfcolaocpcgfikmah</string>
                           </array>
                           <key>ExtensionInstallSources</key>
                           <array>
                              <string>https://auth.clayapp.jp/*</string>
                           </array>
                        </dict>
                     </dict>
                  </array>
               </dict>
            </dict>
         </dict>
      </array>
   </dict>
</plist>

このファイルを、sudo /usr/bin/profiles -I -F ./profile.mobileconfig でインストールしてあげれば、Chromeにポリシーが読み込まれて幸せになれる。


SQL Server Management Studioで、拡張イベントを表示するときの表示上限

Windows で VPN接続をするときに、「Interprocess Communication Depot Error」が出た時の対処方法

$
0
0

Cisco ANyConnectの動作が不安定だったので、アンインストールして再インストール!ってすると、まれに、Interprocess Communication Depot Errorが出てしまい、インストール出来ないことがあります。

The vpn client agent was unable to create the interprocess communication depot.

手順1

  1. スタート→コントロールパネル→ネットワークの状態とタスクの表示をクリックする
  2. アダプターの設定の変更をクリックする
  3. 共有接続を選択し、プロパティを表示する
  4. 共有タブを選択
  5. ネットワークのほかのユーザーに、このコンピューターのインターネット接続をとおしての接続を許可するのチェックボックスのチェックを外し、OKボタンをクリックします。
    image

手順2

  1. スタートボタンを押し、検索ウィンドウに「services.msc」と入力しENterを押します。
  2. Internet Connection Sharing(ICS)をダブルクリックし、スタートアップの種類を無効にします。
    image
  3. コンピューターを再起動します。

Embulkの名前の由来

$
0
0

Embulkの名前の由来が、Twitterで流れていたので雑学としてメモしておきます。

話の流れ

@repeatedly 曰く「今開発中のバルクロードツール,一番の問題は名前だと思う.社内のリポジトリの名前はアレ過ぎてダメ」

@kazuho 曰く「@repeatedly embulkにしましょう #embarkにかけてるつもり」

@frsyuki 曰く「@kazuho ほう! embulkいいですね…ちょうど別の名前を考えつつあったところなのですが、揺らぐ…」

@frsyuki 曰く「新しいものは名前に困る。fluentdも最初は「syslogのjson使えるようになったやつ」だったような。」

結論

embarkにかけてembulk

SQL Serverでリンクサーバーを使用するときにユーザー権限を正しく設定しないと性能問題に遭遇する件

$
0
0

SQL Server 2012以前のSQL Serverでは、リンクサーバーはログインにdd_ddladminまたはdb_owner、sysadminを権限を使用したほうが、良い実行計画の遂行が行われます。

image

上の図のような状態で実験をしてみます。

testリンクサーバーとは、「db_datareader」権限のユーザーを使用。

test1リンクサーバーとは、「db_datareader」と「db_ddladmin」権限のユーザーを使用。

次のクエリを実行する。

select * from [TEST1].[AdventureWorks].[Sales].[SalesOrderDetail]
a INNER JOIN dbo.[SalesOrderHeaderSalesReason] b
ON a.SalesOrderID = b.SalesOrderID
where b.SalesOrderID between 75017 and 75111

select * from [TEST].[AdventureWorks].[Sales].[SalesOrderDetail]
a INNER JOIN dbo.[SalesOrderHeaderSalesReason] b
ON a.SalesOrderID = b.SalesOrderID
where b.SalesOrderID between 75017 and 75111

こんな感じで明らかに実行計画上に差異が発生します。

SQL Server 2016でJSONに対応します

$
0
0

MSDNブログで投稿されていた「JSON support in SQL Server 2016」が元ネタ。

SQL ServerでのJSONサポートは、Microsoft connect siteで、1000以上の投票が集まるリクエストが多いもののひとつです。マイクロソフトは、SQL Server 2016で、デフォルト機能でJSONサポートをすることを発表しました。

まず最初に、nativeのJSONサポートは、nativeのJSONデータ型を提供するわけではありません。SQL Server 2016では、JSONは、NVARCHARデータ型で表現される予定です。

  • 移行
    すでに多くの人がテキストとしてJSONを格納しており、JSONデータ型を提供した場合、新しい機能を使用するには、データベーススキーマーの変更とデータの再ロードが必要になってしまいます。開発者がデータベースの変更をすることなく新しい機能を利用できるように実装します。
  • 機能間の互換性
    NVARCHARは全てのSQL Serverのコンポーネントでサポートしているので、JSONがどこでもサポートされます。Hekaton、カラムストアテーブル、ローレベルセキュリティを含む標準セキュリティポリシー、標準のB-Treeインデックス、FTSインデックス、ストアドプロシージャーでのJSON利用などができます。Hekatonとカラムストアはは、LOB値に対応していないので、少ないデータ量のJSONドキュメントのみ対応します。
  • クライアントサイドのサポート
    C#では、多くの開発者がJSON.NETを使用してビルトインのJObjectやJArray型を使用しています。しかし、まだ標準ではありません。JSONデータ型を追加したとしても、クライアントアプリでは文字列として扱われ、必要があればカスタムパーサーが使われるでしょう。

JSONデータのエクスポート

最初の機能提供は、SQL Server 2016 CTP2で提供されており、「FOR JSON」を使用してJSON形式で結果を取得できるようになっています。

SELECT column, expression, column as alias FROM table1, table2, table3 FOR JSON [AUTO | PATH]

T-SQLクエリの最後に、「FOR JSON」を追加すると、JSONテキスト形式の結果をクライアントに返します。各行は全て、JSONオブジェクトの一部として整形され、セルの値はJSONオブジェクトの値として生成されます。

JSONテキストをリレーショナルテーブルに変換する:OPENJSON

OPENJSONは、JSONテキストを探すテーブル値機能(TVF)です。

SELECT Number, Customer, Date, Quantity
 FROM OPENJSON (@JSalestOrderDetails, '$.OrdersArray')
 WITH (
        Number varchar(200),
        Date datetime,
        Customer varchar(200),
        Quantity int
 ) AS OrdersArray

@JSalesOrderDetailsは、次のような例のOrdersArrayプロパティでJSONオブジェクトの配列を含むテキストです。

‘{"OrdersArray": [

   {"Number":1, "Date": "8/10/2012", "Customer": "Adventure works", "Quantity": 1200},

   {"Number":4, "Date": "5/11/2012", "Customer": "Adventure works", "Quantity": 100},

   {"Number":6, "Date": "1/3/2012", "Customer": "Adventure works", "Quantity": 250},

   {"Number":8, "Date": "12/7/2012", "Customer": "Adventure works", "Quantity": 2200}

]}’

OPENJSONは、プロパティで配列を見つけ、JSONオブジェクトごとに行を返します。結果セットには、4列含まれ、定義は、「WITH」で指定します。OPENJSONは、Number、Date、Customer、Quantityプロパティを見つけ、結果セットのカラムに値を変換します。デフォルトでは、プロパティが見つからない場合はNULLを返します。

JSONを処理するビルトイン関数

  • ISJSON

    NVARCHARテキストにJSONと互換性があるか確認します。
  • JSON_VALUE

    JsonTextをパースし、JSONパスで指定した値を取得します。
  • JSON_QUERY

    JsonTextをパースし、JSONフラグメントを取得します。
SELECT t.Id, t.OrderNumber, t.OrderDate,
 JSON_VALUE(t.JOrderDetails, '$.Order.ShipDate'),
 JSON_QUERY(t.JOrderDetails, '$.Order')
FROM SalesOrderRecord AS t
WHERE ISJSON(t.JOrderDetails) > 0
 AND JSON_VALUE(t.JOrderDetails, '$.Order.ProductType') = 'TV'

JSON インデックス

今のところJSON用のカスタムインデックスを追加する予定はありません。

JSONはプレーンなテキストで、既存のB-Treeやフルテキスト検索インデックスを使用できます。

たとえば次のように、JSON_VALUE関数を使用して、計算列を作成し、その列に標準のインデックスを作成します。

CREATE TABLE SalesOrderRecord (
 Id int PRIMARY KEY IDENTITY,
 OrderNumber NVARCHAR(25) NOT NULL,
 OrderDate DATETIME NOT NULL,
 JOrderDetails NVARCHAR(4000),
 Quantity AS CAST(JSON_VALUE(JOrderDetails, '$.Order.Qty') AS int),
 Price AS JSON_VALUE(JOrderDetails, '$.Order.Price'),
 )
 GO
 CREATE INDEX idxJson
 ON SalesOrderRecord(Quantity)
 INCLUDE (Price);
 

Directory APIでのユーザー権限付与

$
0
0

Google Apps Admin SDKのDirectory APIを使用して、Userを追加登録しようとしたのだけど、次のエラーが出て追加できなかった。
Scopeで、「DirectoryService.Scope.AdminDirectoryUser」を指定しているのにどうしても、権限不足とのエラーが出てしまう。

Google.GoogleApiException はユーザー コードによってハンドルされませんでした。
  HResult=-2146233088
  Message=Google.Apis.Requests.RequestError
Not Authorized to access this resource/api [403]
Errors [
    Message[Not Authorized to access this resource/api] Location[ – ] Reason[forbidden] Domain[global]
]
  Source=Google.Apis
  ServiceName=admin
  StackTrace:

原因は、APIアクセスに使用しているアカウントに権限が無かったから。
具体的には、ドメインの管理コンソールを開いて、管理者の役割から該当アカウントにUser作成権を付与してあげないといけない。

当初は参照しか必要なかったので参照権しか付与していなかった。
User作成権をここで付与してあげないと、API側でいくら付与しようとしたり、Scopeを定義しても権限不足は解消できないのであった。2時間ぐらい悩んだ。。。

directory.orgunits.listのcustomeridの「my_customer」

$
0
0

Google Appsの管理のために、Admin Directory APIを触っています。
Google Appsのアカウントをどの組織に作成するかを選ぶために、組織一覧を取得するためにdirectory.orgunits.listを使用します。

使用方法を確認するために、GoogleのAPIs Explorerにアクセスして、directory.orgunits.listを開きました。

image

あれ?customeridが必須になっているのですが…ここ、何の値を入力するのでしょうか?
ドメイン名?個人アカウント?
どれも違いました。

ドキュメントを見てみました!

If you are an account administrator retrieving all sub-organization units, use my_customer.

うん?いや、だから…my_customerに何を代入するんだって!!!

っと困り果てて試行錯誤すること10分。
よーやく理解しました。

customeridにいれる値は「my_customer」なんだと。ここに何か別の文字列を代入するとかではなく!そのまま文字列を入れるのだと。

image

はい!めでたく、これで結果を取得することができました。ちゃんちゃん。
わかるかーーー!!!


Google Apps Admin SDKでAPI操作するときの権限付与箇所は複数!

$
0
0
  1. API操作に使用するアカウントを用意する
  2. そのアカウントにドメインコンソールで権限付与する
    image
  3. Google Developer Consoleに、そのアカウントでログインしてプロジェクト作成とAPIを有効化する。
    image
  4. ドメインコンソールで、セキュリティを開き、前の手順で作成したクライアント名に権限を付与してあげる。
    image
    ちなみに、この作業をしてなくてもAPI Explorerでの動作確認は成功しちゃうので忘れがち。
    ここで付与してなくて、次の手順でScope指定しちゃうと、次のエラーが出て泣けてくる。
    "access_denied", Description:"Requested client not authorized.", Uri:
  5. 最後は、プログラムからAPIをたたくときに、OAuth認証時にScopで指定してあげればOK。

SQL Server 2016 CTP 2.0 : SQL Server Managed Backup to Azureのまとめ

$
0
0

SQL Server 2016のデータベースエンジンの新機能の1つに「SQL Server Managed Backup to Azure(単にManaged Backupと表記されることもある)」があります。

機能概要

Microsoft Azure Blobストレージに自動的にSQL Serverのバックアップをとったり、管理するための機能です。

バックアップタイミングは次の2パターンを選ぶことができます。

  • データベースのワークロードをベースにした自動バックアップ
  • オプションで設定したバックアップのスケジュール(時間)定義に基づいたバックアップ

Microsoft Azure Blobストレージにバックアップファイルを保存する期間を設定できます。

メリット

これまでは、時間指定のバックアップを設定するか、カスタムコードを書かないと自動バックアップを設定することができなかったのです。

しかし、SQL Server Managed Backup to Windows Azureを使用すると、バックアップファイルの保持期間と、保存場所を指定すれば自動的にバックアップされます。オプションでスケジュールを指定することもできますが不要です。

設定対象

次の範囲で、Managed Backupを設定できます。

  • インスタンスレベル
  • データベースレベル(インスタンスレベルの設定を上書き可能)

インスタンスレベルで定義をしておくと、新しいデータベースを作成したときにも自動的にバックアップされます。

前提条件

次のサービス、アカウント、認証情報が必要です。

  • Microsoft Azure アカウント
  • Azure ストレージアカウント
  • Blobコンテナー
  • Shared Access Signature:SAS(共有アクセス署名)
  • SQL Server Agent サービス

SQL Server 2014 と SQL Server 2016のManaged Backupの機能差異

項目SQL Server 2014SQL Server 2016
名前空間smart_adminmanaged_backup
ストアドsp_set_db_backUP
sp_set_instance_backup
sp_backup_config_basic
sp_backup_config_advance
セキュリティストレージアカウント
アクセスキー
共有アクセス署名
ストレージページBlobブロックBlob

SQL Server 2016では次のような機能特徴がある

  • コストの安いブロックBlobを使用する
  • ストライピングを使用し、最大12TB(ページBlobだと1TB)
  • ストライピングにより、リストア時間の短縮
  • システムデータベースに対応
  • 単純復旧モードのデータベースも利用可能

フルバックアップが取得されるタイミング

  • 機能を有効にしたタイミング
  • 最後のフルバックアップからログが1GB以上拡張したとき
  • 最後のフルバックアップから1週間経過したとき
  • ログチェインが壊れたとき(トランザクションログが消されたとき)

トランザクションログバックアップが取得されるタイミング

  • ログバックアップ履歴が無いとき(通常は機能を有効にしたとき)
  • トランザクションログ要領を5MB以上使用したとき
  • 最後のトランザクションログバックアップから2時間経過したとき
  • フルバックアップが遅延しているとき

バックアップファイルの保存期間

  • 保存期間は最少1日、最大30日を指定できる
  • 保存期間内であれば、指定した時間にポイントタイムリカバリができる

注意事項

  • ブロックBlobの最大サイズは200GB
  • ストライピングを使用することで、最大12TBまで保存可能
  • それ以上の場合は、圧縮を使用する
  • CTP 2.1段階では、GUI(SQL Server Management Studio)での操作はできない
  • ストアドかPowerShellで設定する

機能を有効にする手順

具体的な手順はドキュメントに記載されているので、簡単な流れのみ記載。

  1. Microsoft Azureにサインアップ
  2. ストレージアカウントの作成
  3. Blobコンテナーの作成
  4. 共有アクセス署名(SAS)の作成
  5. SQL証明書の作成
  6. SQL Server Agentサービスの開始
  7. SQL Server Managed Backup to Windows Azureの設定と有効化
  8. ヘルスステータス(エラーや警告)のメール通知の設定と有効化

Azure PowerShellでの操作

Azure PowerShellを使用して、バックアップファイルを格納するコンテナーのSASを取得します。以下の例は、既存のコンテナーのSASを取得する例。

Get-AzurePublishSettingsFile
Import-AzurePublishSettingsFile
Select-AzureSubscription
$context = New-AzureStorageContext -StorageAccountName ***atoya -StorageAccountKey (Get-AzureStorageKey -Storage
New-AzureStorageContainerSASToken -Name pub -Permission rwdl -FullUri -Context $context

 

image

SQL 証明書の作成

次に、SQL証明書を作成します。

CREATE CREDENTIAL [https://***atoya.blob.core.windows.net/pub]
WITH IDENTITY = ‘Shared Access Signature’,
SECRET = ‘sv=2014-02-14&sr=c&sig=********wUKKjd2d8%3D&se=2015-07-08T01%3A55%3A03Z&sp=rwdl’

image

SQL Server Managed Backup to Windows Azureの設定と有効化

Managed Backupを設定します。

Use msdb;
GO
EXEC msdb.managed_backup.sp_backup_config_basic
@enable_backup = 1,
@database_name = ‘test’,
@container_url = ‘https://y****a.blob.core.windows.net/pub’,
@retention_days = 30
GO

ストアドプロシージャーを設定すると、次のように設定しましたと出力されます。

image

裏側では、フルバックアップが実行されます。

Database backed up. Database: test, creation date(time): 2015/05/28(23:11:16), pages dumped: 369, first LSN: 36:376:37, last LSN: 36:395:1, number of dump devices: 1, device information: (FILE=1, TYPE=URL: {‘https://*****.blob.core.windows.net/pub/test_9806c8082c754fdcbca50ae99e2b1763_20150708100900+09.bak’}). This is an informational message only. No user action is required.

SQL Server Agentサービスを使用すると書いてあるので、てっきりジョブ登録されるのかと思ったのですが、ジョブには登録されていません。

image

ヘルスステータス(エラーや警告)のメール通知の設定と有効化

SQLデータベースメールを設定します。

image

SQL Server Agentメールの設定をします。

image

監視を追加します。

EXEC msdb.managed_backup.sp_set_parameter
@parameter_name = ‘SSMBackup2WANotificationEmailIds’,
@parameter_value = ‘<t.yam***ya@***ops.com>’

メール通知はこんな感じのが届きます。

image

バックアップファイルを確認します

バックアップ状況を確認します。

SELECT *
FROM managed_backup.fn_available_backups (‘test’)

image

取得できる情報は次のようなもの。

backup_path
backup_type
expiration_date
database_guid
first_lsn
last_lsn
backup_start_date
backup_finish_date
machine_name
last_recovery_fork_id
first_recovery_fork_id
fork_point_lsn
availability_group_guid

「サーバーがプロセスを実行しようとしません。」というエラーの対処

$
0
0

System.DirectoryServices.AccountManagement を使用して、Active Directoryにユーザーを追加する処理をしていました。

                using (var principalContext = new PrincipalContext(ContextType.Domain, host, ou, AdUser, AdPassword))
                {
                    using (var userprincipal = new UserPrincipalGloops(principalContext))
                    {
                        if (!string.IsNullOrEmpty(lastName))
                        {
                            userprincipal.GivenName = familiyName;
                        }
                        if (!string.IsNullOrEmpty(familiyName))
                        {
                            userprincipal.Surname = familiyName;
                        }
                        if (!string.IsNullOrEmpty(roma))
                        {
                            userprincipal.Name = roma;
                        }
                        if (!string.IsNullOrEmpty(familiyName) && !string.IsNullOrEmpty(lastName))
                        {
                            userprincipal.DisplayName = String.Format("{0} {1}", familiyName, lastName);
                        }
                        if (!string.IsNullOrEmpty(mail))
                        {
                            userprincipal.EmailAddress = mail;
                        }
                        if (!string.IsNullOrEmpty(employeeNumber))
                        {
                            userprincipal.EmployeeNumber = employeeNumber;
                        }
                        if (!string.IsNullOrEmpty(idm))
                        {
                            userprincipal.Description = idm;
                        }
                        if (!string.IsNullOrEmpty(idm))
                        {
                            userprincipal.SamAccountName = account;
                        }
                        userprincipal.SetPassword(password);
                        userprincipal.Enabled                  = true;
                        userprincipal.PasswordNeverExpires     = true;
                        userprincipal.UserCannotChangePassword = true;
                        try
                        {
                            userprincipal.Save();
                        }
                        catch (Exception ex)
                        {
                            Logger.Warn("[Create Ad Account] " + ex.Message, ex);
                            return string.Format("NoCreate:{0}",ex.Message);
                        }
                    }
                }

userprincipa.save()で、例外が発生して、「サーバーがプロセスを実行しようとしません。」と言われちゃいます。(いやいや、実行しろよ!と突っ込みたくなったり)

今回、employee numberに情報を格納するために、プリンシパルの拡張をしていました。

MSDNのサンプルでは、プリンシパルの拡張の冒頭が次のようになっていました。
なので、あまり深く考えずにコピペしたのが運の尽き。

[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("inetOrgPerson")]
public class InetOrgPerson : UserPrincipal
{

「DirectoryObjectClass」が拡張するクラス名を入れておけば良さそうに見えます。実際、それでも既存ユーザーの更新では問題なく動作するように見えます。

しかし、ユーザーの新規作成時には動作しません。
userを指定すると、例外が発生せずにユーザーを新規作成できるようになりました。

[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("user")]
public class UserPrincipalGloops: UserPrincipal
{

2時間ぐらいはまった…。

指定パスに新規ユーザーを作成する方法

$
0
0

System.DirectoryServices.AccountManagement を使用して、Active Directoryにユーザーを新規作成する処理をしていました。

指定したパスにユーザーを作成したい場合は、PrincipalContextをインスタンス化する際に引数を渡してあげればOKでした。

例えば、「OU=employee,OU=Users,DC=domain,DC=sqlazure,DC=jp」にユーザーを追加したい場合は、次のように書けばいい。

var ou = "OU=employee,OU=Users,DC=domain,DC=sqlazure,DC=jp"
var principalContext = new PrincipalContext(ContextType.Domain, hostname, ou, AdUser, AdPassword)
var userprincipal = new UserPrincipalGloops(principalContext)
.
.
.
userprincipal.Save();

HttpClientのBaseAddressを使う方法

$
0
0

System.Net.HttpにあるHttpClientのBaseAddressの使い方がわからなかったので調べてみた。

HttpClientの使用例として、次のサンプルのようにGetAsyncなどの直接URLを記述する例をよく見ます。

using System.Net.Http;
var httpClient = new HttpClient();
var response = await httpClient.GetAsync("http://requestb.in/10v5oew1");

一方で、インテリセンスを見てると、BaseAddressなんてプロパティがあります。
どうやって使い分けるのかがわからなかったので調べてみました。

using System.Net.Http;
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://requestb.in/10v5oew1/"); // こいつは何もの?

調べるのに使用したのは、次のコード。

var baseUri = "";
var getUri = "";
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(baseUri);
var response = await httpClient.GetAsync(getUri);

「baseUri」と「getUri」にいろんなパターンを当てはめて動作を調べてみました。

image

「getUri」にフルパスを指定した場合は、「baseUri」にどのようなUriを指定していも、「getUri」で指定したUriにリクエストをする。上書きをする動き。
「baseUri」が「http: //yahoo.co.jp」で、「getUri」が「http: //google.com」と、完全に異なるドメインを指定したとしても、「getUri」の指定が優先される。

「baseUri」の終わりがスラッシュ(「http: //yahoo.co.jp/foo/」)で、「getUri」の始まりがスラッシュでない文字列(「hoge/foo?bar=1」みたいなの)を指定した場合、単純に文字列結合したUrl(「http: //yahoo.co.jp/foo/hoge/foo?bar=1」)にリクエストする。

それ以外のパターンでは、「baseUri」のホストドメイン+「getUri」が結合されたUriにリクエストされる。

結論

HttpClientのBaseAddressを有効活用したいのなら、

- BaseAddressは、スラッシュで終わる
- GetAsyncなどのメソッドでは、スラッシュではじめない

ことが重要であることがわかりました。

Viewing all 183 articles
Browse latest View live