trapemiyaの日記

hatenablogが新しくなったんで新規一転また2019年1月からちょこちょこ書いてます。C#中心のプログラミングに関するお話です。

タスクスケジューラーからタスクの手動実行で「ユーザーアカウントにこのタスクを実行するアクセス許可がありません」の対処法

タスクスケジューラ―の画面からタスクを手動実行させようとしたところ、「ユーザーアカウントにこのタスクを実行するアクセス許可がありません」というエラーが出て実行できない。
Administratorでログインしているのにもかかわらずである。
ネットを漁ると答えがあった。

The user account does not have permission to run this task
http://pinter.org/archives/7656

要するにタスクの定義ファイルの実行権限が無いのである。
タスクの定義ファイルは、
C:\Windows\System32\Tasks\
配下にある。

私はBunBackupというバックアップを行うアプリ使わせていただいており、
C:\Windows\System32\Tasks\Nagatsuki\BunBackup
のフォルダに、BunBackupというファイルがあるので、これにAdministratorsグループの「読み取りと実行」権限にチェックを付けて無事に解決した。

SQL Server リンクサーバーへアクセスする際のライセンスは?

SQL Serverでリンクサーバーとして設定してあるデータベースへのアクセスのライセンスが気になって確認してみた。
日本マイクロソフト日本オラクルに確認したところSQL ServerOracleも、間接アクセスであっても直接アクセスと同等のライセンスが必要という回答であった。
リンクサーバー元がリンクサーバー先にアクセスするだけなので、その1ユーザーライセンス、もしくは1端末ライセンスだけあればいいというのではないので注意!

まぁ、想像通りでしたが・・・・

これから予算取りです。

【SQL Server】TRANSLATE的な関数を作ってみる

SQL Server 2017からTRANSLATE関数が導入されたことはご存じだろうか?
Oracleなんかには以前よりあったから、よほど要望が強かったんでしょうね。
で、実際にTRANSLATE関数を使いたいけどSQL Server 2016以前が本番環境で動いていることもまだまだたくさんあることでしょう。
そんな方は以下をご覧ください。解決します。

4-1 OracleのTranslate関数を模倣
https://oraclesqlpuzzle.ninja-web.net/sqlserver/sqlserver-4-1.html

ただ、私がやりたかったのは、ビットが立っているところを特定の文字列に変えたかったのです。
例えば、
「0101101」 --> 「 火 木金 日」

これは、先ほどの「OracleのTranslate関数を模倣」に書かれているコードをちょろっと変えるだけで実現できます。
何気にこのような変換する機会はあると思いますので、覚えておくと役に立つかもしれません。

CREATE FUNCTION dbo.Bit列To曜日
(
	@曜日Bit列		char(7)
)
returns nvarchar(7)
as
begin
    declare @返却値		nvarchar(7) = '';
    declare @i			int = 1;
    declare @HitPos		int;

    declare @曜日リスト nchar(7);

    set @曜日リスト = '月火水木金土日';

    if @曜日Bit列 is null
		return null;

    while @i <= len(@曜日Bit列)
    begin
        set @HitPos = CharIndex(SubString(@曜日Bit列, @i, 1),'1111111', @i)

        if @HitPos = 0
            set @返却値 = @返却値 + ' '
        else
            set @返却値 = @返却値 + SubString(@曜日リスト, @HitPos, 1)

        set @i = @i + 1
    end;

    return @返却値;

end

ちょっと注意点を書いておくと、
declare @返却値 nvarchar(7) = '';
と、nvarcharで宣言しているのがポイントです。これをncharと固定長で書いてしまうと
set @返却値 = @返却値 + ' '
といったところで問題が発生します。もし、@返却値がnchar(7)の固定長だとすると、上記のsetの結果は、@返却値に空白が8文字分入っている状態になります。
実はT-SQLでストアドプロシージャやストアドファンクションを書く際には型の宣言が非常に重要で、これを誤っていると想定しない結果が返ってくることになります。
数値型でもそうです。思わぬバグにつながりますので注意しましょう。

select 5 / 2;

#結果は、2

select 5 / CONVERT(decimal, 2);

#結果は、2.500000

OPENQUERYの結果を変数に入れる

OPENQUERYの結果を変数に入れるには、次のようにOUTPUTを付けた変数を定義し、それに渡します。

declare @rowcnt	int;

set @sqlwk = 'select @rowcnt = count(*) from openquery(edpsrd, ''
select 契約番号
from mine.dbo.契約テーブル
where  契約番号 = ''''' + @契約番号 + ''''''
+ ''')';

EXEC sp_executesql @sqlwk, N'@rowcnt int output', @rowcnt output;

outputはoutと省略することもできます。

次のエラーが出たら、outputを付けるのを忘れています。

仮パラメーター "XXX" は OUTPUT パラメーターとして宣言されませんでしたが、実パラメーターによって要求された出力に渡されました。

WPFのコマンドボタン等の表示で改行する方法のまとめ

WPFのコマンドボタン等の表示で改行する方法として、まずXAMLだと以下の5つの方法を思いつきます。

■1つめ 改行位置に&#xa;を使う

<Button Text="1行目の文字列&#xa;2行目の文字列" />
■2つめ 改行位置に&#10;を使う

<Button Text="1行目の文字列&#10;2行目の文字列" />
■3つめ 改行位置に&#13;を使う

<Button Text="1行目の文字列&#13;2行目の文字列" />
■4つめ <LineBreak />を使う

<Button>
    <TextBlock>1行目の文字列<LineBreak />2行目の文字列</TextBlock>
</Button>
■5つめ xml:space="preserve"を使う

<Button xml:space="preserve">1行目の文字列
2行目の文字列
</Button>

1つ目から3つ目まではパターンは一緒ですね。特に、&#xa;と&#10;は16進数表示か10進数表示かの違いでしかなく・・・

コードから指定する場合は、¥nを使います。

button1.Content = "1行目の文字列¥n2行目の文字列";

あと、改行位置を指定するわけではなく、右端に来たら単に折り返すには以下のようにします。場合によっては有効かも。

<Button>
    <TextBlock TextWrapping="Wrap" Text="文字列が右端で折り返します" />
</Button>

他にあれば教えて下さい。




Windows FormアプリケーションからWPFのWindowを開いた際にTextBoxで半角入力ができない、カーソルが効かない

過去に作成したWindows Formアプリケーションの機能アップをすべく、その部分はWPFで作成してます。
さて、問題にぶつかりました。Windows FormアプリケーションからWPFのWindowを開いた際に、そのWindowのTextBoxではなぜか半角入力を受け付けてくれません。
全角入力は問題なくできます。
いろいろ悩みましたが、答えはググればすぐでしたorz

xamlのテキストボックス(System.Windows.Controls.TextBox)で半角英数が入力できない
https://social.msdn.microsoft.com/Forums/sqlserver/ja-JP/bd20e0f8-777b-4aad-8d87-47f813aef715/xaml123981248612461124731248812508124831246312473systemwindowscontrols?forum=netfxgeneralja

このページで紹介してあるリンク先の以下のページに解決策があります。

Windows Form opening WPF window
https://social.msdn.microsoft.com/Forums/vstudio/en-US/442782b1-00a1-4e2e-9cc6-ae99b6699126/windows-form-opening-wpf-window?forum=wpf

簡単に言えば、WindowをShow()した後に、以下のメソッドを実行するだけで良い。

System.Windows.Threading.Dispatcher.Run();

もしくは上記の代わりに、以下でも良い。

System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(window);
window.Show();

EnableModelessKeyboardInteropを実行するには、 WindowsFormsIntegration.dll を参照設定する必要がある。

(参考)
WPF Window を Windows フォームから起動した場合の落とし穴
https://hilapon.hatenadiary.org/entry/20100618/1276855276


まぁ、WindowsフォームとWPFは仕組みが全く違いますから仕方ないですわねぇ・・・

【追記 2020-03-12】

System.Windows.Threading.Dispatcher.Run();

が、お勧めということが分かった。

System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(window);
window.Show();

だと、この開いた画面からさらに別のWPFの画面を開くと、同様の症状が出てしまう。

【SQL ServerからOracleへのリンクサーバー】列’xxx’に必要なデータ長に一致しないデータが返されました。必要な (最大) データ長は xxですが、返されたデータ長は xx です。

SQL ServerからOracleへのリンクサーバーを設定している状態で、例えば以下のSQLを実行すると次のエラーが出る。

select * from openquery(edpstv, 'select '''' as 有無 from BSS.契約 ')

リンク サーバー 'edpstv' の OLE DB プロバイダー 'OraOLEDB.Oracle' から、列 '[OraOLEDB.Oracle].有無' に必要なデータ長に一致しないデータが返されました。必要な (最大) データ長は 4 ですが、返されたデータ長は 2 です。

はっ? 何のこと・・・

ネットを漁ると、「Microsoft OLE DB Provider for ORACLE」に変更したらうまく行ったという記述があったが、これは廃止になるものなので基本的には使用してはいけない。

Microsoft OLE DB Provider for Oracle の概要
https://docs.microsoft.com/ja-jp/sql/ado/guide/appendixes/microsoft-ole-db-provider-for-oracle?view=sql-server-ver15

型を指定していないのがいけないのかと思い、次のように型を指定してあげたらうまく行った。

select * from openquery(edpstv, 'select cast('''' as varchar(2)) from BSS.契約 ')

でもやっぱり謎だなぁ・・・